summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcvs2svn <cvs2svn@FreeBSD.org>1995-08-30 17:42:29 +0000
committercvs2svn <cvs2svn@FreeBSD.org>1995-08-30 17:42:29 +0000
commit09adf59b71be5536e90072a21ff0a298de13b31e (patch)
tree5472a1168e90c3da5a19b92d4eec77fdec82325a
parent11ae5136afc310ef71c58826e0faa94cc2b415f4 (diff)
Notes
-rw-r--r--eBones/Copyright.MIT24
-rw-r--r--eBones/Copyright.SIPB23
-rw-r--r--eBones/README.libdes56
-rw-r--r--eBones/include/ChangeLog25
-rw-r--r--eBones/include/addr_comp.h35
-rw-r--r--eBones/include/admin_server.h42
-rw-r--r--eBones/include/conf-bsd386i.h16
-rw-r--r--eBones/include/conf-bsdapollo.h21
-rw-r--r--eBones/include/conf-bsdibm032.h18
-rw-r--r--eBones/include/conf-bsdm68k.h16
-rw-r--r--eBones/include/conf-bsdsparc.h17
-rw-r--r--eBones/include/conf-bsdtahoe.h16
-rw-r--r--eBones/include/conf-bsdvax.h22
-rw-r--r--eBones/include/conf-ibm370.h15
-rw-r--r--eBones/include/conf-pc.h16
-rw-r--r--eBones/include/conf-pyr.h15
-rw-r--r--eBones/include/conf-ultmips2.h17
-rw-r--r--eBones/include/conf.h73
-rw-r--r--eBones/include/highc.h32
-rw-r--r--eBones/include/kdc.h36
-rw-r--r--eBones/include/klog.h39
-rw-r--r--eBones/include/krb_conf.h29
-rw-r--r--eBones/include/lsb_addr_comp.h40
-rw-r--r--eBones/include/osconf.h51
-rw-r--r--eBones/include/passwd_server.h28
-rw-r--r--eBones/include/principal.h18
-rw-r--r--eBones/include/prot.h92
-rw-r--r--eBones/lib/libacl/acl_files.doc107
-rw-r--r--eBones/patchlevel.h6
-rw-r--r--eBones/usr.sbin/kdb_edit/kdb_edit.858
-rw-r--r--eBones/usr.sbin/kdb_edit/time.h45
-rw-r--r--gnu/libexec/uucp/libunix/failed.c26
-rw-r--r--gnu/libexec/uucp/libunix/sync.c42
-rw-r--r--gnu/libexec/uucp/libunix/tcp.c444
-rw-r--r--gnu/libexec/uucp/libunix/tli.c628
-rw-r--r--gnu/libexec/uucp/libunix/uid.c116
-rw-r--r--gnu/libexec/uucp/libuuconf/strip.c50
-rw-r--r--gnu/libexec/uucp/uucico/proty.c660
-rw-r--r--gnu/usr.bin/ld/rtld/rtld.1144
-rw-r--r--gnu/usr.sbin/ypserv/svc_run.c85
-rw-r--r--lib/libc/net/res_config.h7
-rw-r--r--lib/libtermcap/tospeed.c72
-rw-r--r--lkm/linux/Makefile16
-rw-r--r--lkm/linux/linux3
-rw-r--r--lkm/linux/linux.c58
-rw-r--r--secure/libexec/Makefile6
-rw-r--r--secure/libexec/Makefile.inc4
-rw-r--r--share/doc/handbook/install.sgml652
-rw-r--r--share/doc/handbook/kerneldebug.sgml425
-rw-r--r--share/doc/handbook/relnotes.sgml503
-rw-r--r--share/doc/handbook/userppp.sgml360
-rw-r--r--share/examples/find_interface/Makefile6
-rw-r--r--share/examples/find_interface/README9
-rw-r--r--share/syscons/keymaps/spanish.iso.kbd109
-rw-r--r--sys/i386/include/ioctl_meteor.h138
-rw-r--r--sys/i386/isa/cyreg.h57
-rw-r--r--sys/i386/isa/si_code.c804
-rw-r--r--sys/i386/isa/sireg.h69
-rw-r--r--sys/i386/isa/sound/Readme.aedsp166
-rw-r--r--sys/i386/isa/sound/Readme.modules87
-rw-r--r--sys/i386/isa/sound/ad1848_mixer.h130
-rw-r--r--sys/i386/isa/sound/aedsp16.c838
-rw-r--r--sys/i386/isa/sound/coproc.h12
-rw-r--r--sys/i386/isa/sound/hex2hex.h97
-rw-r--r--sys/i386/isa/sound/mad16.h91
-rw-r--r--sys/i386/isa/sound/soundvers.h1
-rw-r--r--sys/i386/isa/sound/sscape.c1120
-rw-r--r--sys/i386/isa/sound/trix.c323
-rw-r--r--sys/i386/linux/imgact_linux.c235
-rw-r--r--sys/i386/linux/linux.h406
-rw-r--r--sys/i386/linux/linux_dummy.c316
-rw-r--r--sys/i386/linux/linux_file.c436
-rw-r--r--sys/i386/linux/linux_generic.c63
-rw-r--r--sys/i386/linux/linux_ioctl.c495
-rw-r--r--sys/i386/linux/linux_ipc.c308
-rw-r--r--sys/i386/linux/linux_misc.c660
-rw-r--r--sys/i386/linux/linux_signal.c259
-rw-r--r--sys/i386/linux/linux_socket.c595
-rw-r--r--sys/i386/linux/linux_stats.c273
-rw-r--r--sys/i386/linux/linux_sysent.c367
-rw-r--r--sys/i386/scsi/93cx6.c175
-rw-r--r--sys/i386/scsi/93cx6.h52
-rw-r--r--sys/pccard/cis.h250
-rw-r--r--sys/pccard/i82365.h207
-rw-r--r--sys/pccard/skel.c189
-rw-r--r--usr.bin/at/LEGAL29
-rw-r--r--usr.bin/chpass/pw_yp.c241
-rw-r--r--usr.bin/chpass/pw_yp.h45
-rw-r--r--usr.bin/ee/Makefile18
-rw-r--r--usr.bin/ee/README116
-rw-r--r--usr.bin/ee/doc/Artistic117
-rw-r--r--usr.bin/ee/doc/ee.i18n.guide141
-rw-r--r--usr.bin/ee/doc/new_curse.c3574
-rw-r--r--usr.bin/ee/doc/new_curse.h255
-rw-r--r--usr.bin/ee/ee.c4795
-rw-r--r--usr.bin/ee/nls/en_US.ISO_8859-1/ee.msg170
-rw-r--r--usr.bin/killall/Makefile7
-rw-r--r--usr.sbin/cdcontrol/Makefile4
-rw-r--r--usr.sbin/cdcontrol/cdcontrol.1144
-rw-r--r--usr.sbin/cdcontrol/cdcontrol.c622
-rw-r--r--usr.sbin/mrouted/cfparse.y564
-rw-r--r--usr.sbin/mrouted/mtrace.8498
-rw-r--r--usr.sbin/mrouted/pathnames.h25
-rw-r--r--usr.sbin/mrouted/rsrr.c498
-rw-r--r--usr.sbin/mrouted/rsrr.h138
-rw-r--r--usr.sbin/mrouted/testrsrr/Makefile14
-rw-r--r--usr.sbin/mrouted/testrsrr/testrsrr.c124
-rw-r--r--usr.sbin/named/tools/ndc/Makefile25
-rw-r--r--usr.sbin/named/tools/ndc/ndc.8127
-rw-r--r--usr.sbin/named/tools/ndc/ndc.sh86
-rw-r--r--usr.sbin/pkg_install/lib/ftp.c424
-rw-r--r--usr.sbin/pkg_install/lib/ftp.h26
-rw-r--r--usr.sbin/sicontrol/Makefile5
-rw-r--r--usr.sbin/sicontrol/sicontrol.c585
-rw-r--r--usr.sbin/spkrtest/spkrtest.832
-rw-r--r--usr.sbin/spkrtest/spkrtest.pl96
-rw-r--r--usr.sbin/tcpdump/tcpdump/print-krb.c294
-rw-r--r--usr.sbin/xntpd/conf/ntp.conf.dcf7719
118 files changed, 28390 insertions, 0 deletions
diff --git a/eBones/Copyright.MIT b/eBones/Copyright.MIT
new file mode 100644
index 0000000000000..cd1d89bc88d79
--- /dev/null
+++ b/eBones/Copyright.MIT
@@ -0,0 +1,24 @@
+# $Id: Copyright.MIT,v 1.3 1995/07/18 16:34:16 mark Exp $
+
+The following Copyright notice applies to the original Bones package.
+
+/*-
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
diff --git a/eBones/Copyright.SIPB b/eBones/Copyright.SIPB
new file mode 100644
index 0000000000000..5e6c38af38e7f
--- /dev/null
+++ b/eBones/Copyright.SIPB
@@ -0,0 +1,23 @@
+# $Id: Copyright.SIPB,v 1.3 1995/07/18 16:34:18 mark Exp $
+
+The following Copyright notice applies to parts of the Bones package.
+See source code for exact references.
+
+/*-
+Copyright 1987 by the Student Information Processing Board
+ of the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this software
+and its documentation for any purpose and without fee is
+hereby granted, provided that the above copyright notice
+appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation,
+and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+M.I.T. and the M.I.T. S.I.P.B. make no representations about
+the suitability of this software for any purpose. It is
+provided "as is" without express or implied warranty.
+
+ */
+
diff --git a/eBones/README.libdes b/eBones/README.libdes
new file mode 100644
index 0000000000000..a2aa1eb43099b
--- /dev/null
+++ b/eBones/README.libdes
@@ -0,0 +1,56 @@
+
+ libdes, Version 3.00 93/10/07
+
+ Copyright (c) 1993, Eric Young
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ a) the GNU General Public License as published by the Free
+ Software Foundation; either version 1, or (at your option) any
+ later version, or
+
+ b) the "Artistic License" which comes with this Kit.
+
+ 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 either
+ the GNU General Public License or the Artistic License for more details.
+
+ You should have received a copy of the Artistic License with this
+ Kit, in the file named "Artistic". If not, I'll be glad to provide one.
+
+ You should also 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.
+---
+This kit builds a DES encryption library and a DES encryption program.
+It suports ecb, cbc, ofb, cfb, triple ecb, triple cbc and MIT's pcbc
+encryption modes and also has a fast implementation of crypt(3).
+It contains support routines to read keys from a terminal,
+generate a random key, generate a key from an arbitary length string,
+read/write encrypted data from/to a file descriptor.
+
+The implementation was written so as to conform with the manual entry
+for the des_crypt(3) library routines from MIT's project Athena.
+
+destest should be run after compilation to test the des routines.
+rpw should be run after compilation to test the read password routines.
+The des program is a replacement for the sun des command. I believe it
+conforms to the sun version.
+
+The Imakefile is setup for use in the kerberos distribution.
+
+These routines are best compiled with gcc or any other good
+optimising compiler.
+Just turn you optimiser up to the highest settings and run destest
+after the build to make sure everything works.
+
+I believe these routines are close to the fastest and most portable DES
+routines that use small lookup tables (4.5k) that are publicly available.
+The fcrypt routine is faster than ufc's fcrypt (when compiling with
+gcc2 -O2) on the sparc 2 (1410 vs 1270) but is not so good on other machines
+(on a sun3/260 168 vs 336).
+
+Eric Young (eay@psych.psy.uq.oz.au)
diff --git a/eBones/include/ChangeLog b/eBones/include/ChangeLog
new file mode 100644
index 0000000000000..77bc7552a42fd
--- /dev/null
+++ b/eBones/include/ChangeLog
@@ -0,0 +1,25 @@
+# $Id: ChangeLog,v 1.3 1995/07/18 16:35:58 mark Exp $
+
+Mon Mar 21 15:48:59 MET 1994 Piero Serini
+ * 1st port to FreeBSD
+
+Tue Nov 29 11:52:51 1988 John T Kohl (jtkohl at lycus)
+
+ * osconf.h: add #ifdef's for SUN processors (bsd/m68k)
+
+ * conf-bsdm68k.h: new file for BSD unix/M68000-based unix boxes
+
+Mon Sep 12 14:33:58 1988 Bill Sommerfeld (wesommer at ra)
+
+ * des_conf.h: deleted file (superceded by conf.h)
+
+ * des.h: remove #include of des_conf.h
+
+ * des.h: remove internal details (sbox structure, bit_{32,64}) from
+interface.
+ Rename data types.
+ Add #defines, turned off if NCOMPAT, for compatibility with old
+ versions.
+
+
+
diff --git a/eBones/include/addr_comp.h b/eBones/include/addr_comp.h
new file mode 100644
index 0000000000000..2421bc683de5a
--- /dev/null
+++ b/eBones/include/addr_comp.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1987, 1988, 1989 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Include file for address comparison macros.
+ *
+ * from: addr_comp.h,v 4.0 89/01/23 09:57:44 jtkohl Exp $
+ * $Id: addr_comp.h,v 1.3 1995/07/18 16:36:01 mark Exp $
+ */
+
+#ifndef ADDR_COMP_DEFS
+#define ADDR_COMP_DEFS
+
+/*
+** Look boys and girls, a big kludge
+** We need to compare the two internet addresses in network byte order, not
+** local byte order. This is a *really really slow way of doing that*
+** But.....
+** .....it works
+** so we run with it
+**
+** long_less_than gets fed two (u_char *)'s....
+*/
+
+#define u_char_comp(x,y) \
+ (((x)>(y))?(1):(((x)==(y))?(0):(-1)))
+
+#define long_less_than(x,y) \
+ (u_char_comp((x)[0],(y)[0])?u_char_comp((x)[0],(y)[0]): \
+ (u_char_comp((x)[1],(y)[1])?u_char_comp((x)[1],(y)[1]): \
+ (u_char_comp((x)[2],(y)[2])?u_char_comp((x)[2],(y)[2]): \
+ (u_char_comp((x)[3],(y)[3])))))
+
+#endif /* ADDR_COMP_DEFS */
diff --git a/eBones/include/admin_server.h b/eBones/include/admin_server.h
new file mode 100644
index 0000000000000..ca0977da63b22
--- /dev/null
+++ b/eBones/include/admin_server.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Include file for the Kerberos administration server.
+ *
+ * from: admin_server.h,v 4.7 89/01/11 11:59:42 steiner Exp $
+ * $Id: admin_server.h,v 1.3 1995/07/18 16:36:03 mark Exp $
+ */
+
+#ifndef ADMIN_SERVER_DEFS
+#define ADMIN_SERVER_DEFS
+
+#define PW_SRV_VERSION 2 /* version number */
+
+#define INSTALL_NEW_PW (1<<0) /*
+ * ver, cmd, name, password,
+ * old_pass, crypt_pass, uid
+ */
+
+#define ADMIN_NEW_PW (2<<1) /*
+ * ver, cmd, name, passwd,
+ * old_pass
+ * (grot), crypt_pass (grot)
+ */
+
+#define ADMIN_SET_KDC_PASSWORD (3<<1) /* ditto */
+#define ADMIN_ADD_NEW_KEY (4<<1) /* ditto */
+#define ADMIN_ADD_NEW_KEY_ATTR (5<<1) /*
+ * ver, cmd, name, passwd,
+ * inst, attr (grot)
+ */
+#define INSTALL_REPLY (1<<1) /* ver, cmd, name, password */
+#define RETRY_LIMIT 1
+#define TIME_OUT 30
+#define USER_TIMEOUT 90
+#define MAX_KPW_LEN 40
+
+#define KADM "changepw" /* service name */
+
+#endif /* ADMIN_SERVER_DEFS */
diff --git a/eBones/include/conf-bsd386i.h b/eBones/include/conf-bsd386i.h
new file mode 100644
index 0000000000000..a009450d70e0c
--- /dev/null
+++ b/eBones/include/conf-bsd386i.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 1989 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Machine-type definitions: Sun 386i using SunOS (~BSD)
+ *
+ * from: conf-bsd386i.h,v 4.0 89/12/19 13:26:55 jtkohl Exp $
+ * $Id: conf-bsd386i.h,v 1.3 1995/07/18 16:36:05 mark Exp $
+ */
+
+#define BITS32
+#define BIG
+#define LSBFIRST
+#define BSDUNIX
+
diff --git a/eBones/include/conf-bsdapollo.h b/eBones/include/conf-bsdapollo.h
new file mode 100644
index 0000000000000..12dc5806c8e55
--- /dev/null
+++ b/eBones/include/conf-bsdapollo.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * from: conf-bsdapollo.h,v 4.1 89/01/24 14:26:22 jtkohl Exp $
+ * $Id: conf-bsdapollo.h,v 1.3 1995/07/18 16:36:06 mark Exp $
+ */
+
+#define BSDUNIX
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define DES_SHIFT_SHIFT
+/*
+ * As of SR10, the C compiler claims to be __STDC__, but doesn't support
+ * const. Sigh.
+ */
+#define const
+
+
diff --git a/eBones/include/conf-bsdibm032.h b/eBones/include/conf-bsdibm032.h
new file mode 100644
index 0000000000000..8331498e55dc5
--- /dev/null
+++ b/eBones/include/conf-bsdibm032.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Machine-type definitions: IBM 032 (RT/PC)
+ *
+ * from: conf-bsdibm032.h,v 4.0 89/01/23 09:58:01 jtkohl Exp $
+ * $Id: conf-bsdibm032.h,v 1.3 1995/07/18 16:36:08 mark Exp $
+ */
+
+#define BSDUNIX
+#define IBMWS
+#define IBMWSASM
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define MUSTALIGN
diff --git a/eBones/include/conf-bsdm68k.h b/eBones/include/conf-bsdm68k.h
new file mode 100644
index 0000000000000..9e60e060e509a
--- /dev/null
+++ b/eBones/include/conf-bsdm68k.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Machine-type definitions: 68000 with BSD Unix, e.g. SUN
+ *
+ * from: conf-bsdm68k.h,v 4.0 88/11/29 11:46:58 jtkohl Exp $
+ * $Id: conf-bsdm68k.h,v 1.3 1995/07/18 16:36:10 mark Exp $
+ */
+
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define BSDUNIX
+
diff --git a/eBones/include/conf-bsdsparc.h b/eBones/include/conf-bsdsparc.h
new file mode 100644
index 0000000000000..7359aec78ec3f
--- /dev/null
+++ b/eBones/include/conf-bsdsparc.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Machine-type definitions: SPARC with BSD Unix, e.g. SUN-4
+ *
+ * from: conf-bsdsparc.h,v 4.0 89/06/02 13:04:06 jtkohl Exp $
+ * $Id: conf-bsdsparc.h,v 1.3 1995/07/18 16:36:12 mark Exp $
+ */
+
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define BSDUNIX
+#define MUSTALIGN
+
diff --git a/eBones/include/conf-bsdtahoe.h b/eBones/include/conf-bsdtahoe.h
new file mode 100644
index 0000000000000..fa8c462cf3af6
--- /dev/null
+++ b/eBones/include/conf-bsdtahoe.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 1989 by the Regents of the University of California
+ *
+ * Machine Description : TAHOE.
+ *
+ * from: conf-bsdtahoe.h,v 4.0 89/08/30 11:06:53 jtkohl Exp $
+ * $Id: conf-bsdtahoe.h,v 1.3 1995/07/18 16:36:14 mark Exp $
+ */
+
+#define TAHOE
+#define BSDUNIX
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define MUSTALIGN
+#define NOASM
diff --git a/eBones/include/conf-bsdvax.h b/eBones/include/conf-bsdvax.h
new file mode 100644
index 0000000000000..ef0c05228fc0b
--- /dev/null
+++ b/eBones/include/conf-bsdvax.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Machine-type definitions: VAX
+ *
+ * from: conf-bsdvax.h,v 4.0 89/01/23 09:58:12 jtkohl Exp $
+ * $Id: conf-bsdvax.h,v 1.3 1995/07/18 16:36:15 mark Exp $
+ */
+
+#define VAX
+#define BITS32
+#define BIG
+#define LSBFIRST
+#define BSDUNIX
+
+#ifndef __STDC__
+#ifndef NOASM
+#define VAXASM
+#endif /* no assembly */
+#endif /* standard C */
diff --git a/eBones/include/conf-ibm370.h b/eBones/include/conf-ibm370.h
new file mode 100644
index 0000000000000..7b8b504ba4deb
--- /dev/null
+++ b/eBones/include/conf-ibm370.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Machine-type definitions: IBM 370
+ *
+ * from: conf-ibm370.h,v 4.0 89/01/23 09:58:19 jtkohl Exp $
+ * $Id: conf-ibm370.h,v 1.3 1995/07/18 16:36:17 mark Exp $
+ */
+
+/* What else? */
+#define BIG
+#define NONASCII
+#define SHORTNAMES
diff --git a/eBones/include/conf-pc.h b/eBones/include/conf-pc.h
new file mode 100644
index 0000000000000..4b633ffdba33d
--- /dev/null
+++ b/eBones/include/conf-pc.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Machine-type definitions: IBM PC 8086
+ *
+ * from: conf-pc.h,v 4.0 89/01/23 09:58:26 jtkohl Exp $
+ * $Id: conf-pc.h,v 1.3 1995/07/18 16:36:19 mark Exp $
+ *
+ */
+
+#define IBMPC
+#define BITS16
+#define CROSSMSDOS
+#define LSBFIRST
diff --git a/eBones/include/conf-pyr.h b/eBones/include/conf-pyr.h
new file mode 100644
index 0000000000000..f47c2155031fd
--- /dev/null
+++ b/eBones/include/conf-pyr.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 1989 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Machine-type definitions: Pyramid
+ *
+ * from: conf-pyr.h,v 4.0 89/12/19 13:27:16 jtkohl Exp $
+ * $Id: conf-pyr.h,v 1.3 1995/07/18 16:36:20 mark Exp $
+ */
+
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define BSDUNIX
diff --git a/eBones/include/conf-ultmips2.h b/eBones/include/conf-ultmips2.h
new file mode 100644
index 0000000000000..9733090aa2aaf
--- /dev/null
+++ b/eBones/include/conf-ultmips2.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Machine-type definitions: DECstation 3100 (MIPS R2000)
+ *
+ * from: conf-ultmips2.h,v 4.0 89/01/23 09:58:32 jtkohl Exp $
+ * $Id: conf-ultmips2.h,v 1.3 1995/07/18 16:36:22 mark Exp $
+ */
+
+#define MIPS2
+#define BITS32
+#define BIG
+#define LSBFIRST
+#define BSDUNIX
+#define MUSTALIGN
diff --git a/eBones/include/conf.h b/eBones/include/conf.h
new file mode 100644
index 0000000000000..64797e6bdfc46
--- /dev/null
+++ b/eBones/include/conf.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Configuration info for operating system, hardware description,
+ * language implementation, C library, etc.
+ *
+ * This file should be included in (almost) every file in the Kerberos
+ * sources, and probably should *not* be needed outside of those
+ * sources. (How do we deal with /usr/include/des.h and
+ * /usr/include/krb.h?)
+ *
+ * from: conf.h,v 4.0 89/01/23 09:58:40 jtkohl Exp $
+ * $Id: conf.h,v 1.3 1995/07/18 16:36:24 mark Exp $
+ */
+
+#ifndef _CONF_H_
+
+#include "osconf.h"
+
+#ifdef SHORTNAMES
+#include "names.h"
+#endif
+
+/*
+ * Language implementation-specific definitions
+ */
+
+/* special cases */
+#ifdef __HIGHC__
+/* broken implementation of ANSI C */
+#undef __STDC__
+#endif
+
+#ifndef __STDC__
+#define const
+#define volatile
+#define signed
+typedef char *pointer; /* pointer to generic data */
+#define PROTOTYPE(p) ()
+#else
+typedef void *pointer;
+#define PROTOTYPE(p) p
+#endif
+
+/* Does your compiler understand "void"? */
+#ifdef notdef
+#define void int
+#endif
+
+/*
+ * A few checks to see that necessary definitions are included.
+ */
+
+/* byte order */
+
+#ifndef MSBFIRST
+#ifndef LSBFIRST
+Error: byte order not defined.
+#endif
+#endif
+
+/* machine size */
+#ifndef BITS16
+#ifndef BITS32
+Error: how big is this machine anyways?
+#endif
+#endif
+
+/* end of checks */
+
+#endif /* _CONF_H_ */
diff --git a/eBones/include/highc.h b/eBones/include/highc.h
new file mode 100644
index 0000000000000..7ff2f7cbd5e04
--- /dev/null
+++ b/eBones/include/highc.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Known breakage in the version of Metaware's High C compiler that
+ * we've got available....
+ *
+ * from: highc.h,v 4.0 89/01/23 09:59:15 jtkohl Exp $
+ * $Id: highc.h,v 1.3 1995/07/18 16:36:27 mark Exp $
+ */
+
+#define const
+/*#define volatile*/
+
+/*
+ * Some builtin functions we can take advantage of for inlining....
+ */
+
+#define abs _abs
+/* the _max and _min builtins accept any number of arguments */
+#undef MAX
+#define MAX(x,y) _max(x,y)
+#undef MIN
+#define MIN(x,y) _min(x,y)
+/*
+ * I'm not sure if 65535 is a limit for this builtin, but it's
+ * reasonable for a string length. Or is it?
+ */
+/*#define strlen(s) _find_char(s,65535,0)*/
+#define bzero(ptr,len) _fill_char(ptr,len,'\0')
+#define bcmp(b1,b2,len) _compare(b1,b2,len)
diff --git a/eBones/include/kdc.h b/eBones/include/kdc.h
new file mode 100644
index 0000000000000..70756a49afde0
--- /dev/null
+++ b/eBones/include/kdc.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Include file for the Kerberos Key Distribution Center.
+ *
+ * from: kdc.h,v 4.1 89/01/24 17:54:04 jon Exp $
+ * $Id: kdc.h,v 1.3 1995/07/18 16:36:29 mark Exp $
+ */
+
+#ifndef KDC_DEFS
+#define KDC_DEFS
+
+#define S_AD_SZ sizeof(struct sockaddr_in)
+
+#define max(a,b) (a>b ? a : b)
+#define min(a,b) (a<b ? a : b)
+
+#define TRUE 1
+#define FALSE 0
+
+#define MKEYFILE "/etc/kerberosIV/master_key"
+#define K_LOGFIL "/var/log/kpropd.log"
+#define KS_LOGFIL "/var/log/kerberos_slave.log"
+#define KRB_ACL "/etc/kerberosIV/kerberos.acl"
+#define KRB_PROG "./kerberos"
+
+#define ONE_MINUTE 60
+#define FIVE_MINUTES (5 * ONE_MINUTE)
+#define ONE_HOUR (60 * ONE_MINUTE)
+#define ONE_DAY (24 * ONE_HOUR)
+#define THREE_DAYS (3 * ONE_DAY)
+
+#endif /* KDC_DEFS */
+
diff --git a/eBones/include/klog.h b/eBones/include/klog.h
new file mode 100644
index 0000000000000..c8ca55778696b
--- /dev/null
+++ b/eBones/include/klog.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * This file defines the types of log messages logged by klog. Each
+ * type of message may be selectively turned on or off.
+ *
+ * from: klog.h,v 4.7 89/01/24 17:55:07 jon Exp $
+ * $Id: klog.h,v 1.3 1995/07/18 16:36:30 mark Exp $
+ */
+
+#ifndef KLOG_DEFS
+#define KLOG_DEFS
+
+#define KRBLOG "/var/log/kerberos.log" /* master server */
+#define KRBSLAVELOG "/var/log/kerberos_slave.log" /* master server */
+#define NLOGTYPE 100 /* Maximum number of log msg types */
+
+#define L_NET_ERR 1 /* Error in network code */
+#define L_NET_INFO 2 /* Info on network activity */
+#define L_KRB_PERR 3 /* Kerberos protocol errors */
+#define L_KRB_PINFO 4 /* Kerberos protocol info */
+#define L_INI_REQ 5 /* Request for initial ticket */
+#define L_NTGT_INTK 6 /* Initial request not for TGT */
+#define L_DEATH_REQ 7 /* Request for server death */
+#define L_TKT_REQ 8 /* All ticket requests using a tgt */
+#define L_ERR_SEXP 9 /* Service expired */
+#define L_ERR_MKV 10 /* Master key version incorrect */
+#define L_ERR_NKY 11 /* User's key is null */
+#define L_ERR_NUN 12 /* Principal not unique */
+#define L_ERR_UNK 13 /* Principal Unknown */
+#define L_ALL_REQ 14 /* All requests */
+#define L_APPL_REQ 15 /* Application requests (using tgt) */
+#define L_KRB_PWARN 16 /* Protocol warning messages */
+
+char *klog();
+
+#endif /* KLOG_DEFS */
diff --git a/eBones/include/krb_conf.h b/eBones/include/krb_conf.h
new file mode 100644
index 0000000000000..ac7c2a83ec70f
--- /dev/null
+++ b/eBones/include/krb_conf.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * This file contains configuration information for the Kerberos library
+ * which is machine specific; currently, this file contains
+ * configuration information for the vax, the "ibm032" (RT), and the
+ * "PC8086" (IBM PC).
+ *
+ * Note: cross-compiled targets must appear BEFORE their corresponding
+ * cross-compiler host. Otherwise, both will be defined when running
+ * the native compiler on the programs that construct cross-compiled
+ * sources.
+ *
+ * from: krb_conf.h,v 4.0 89/01/23 09:59:27 jtkohl Exp $
+ * $Id: krb_conf.h,v 1.3 1995/07/18 16:36:36 mark Exp $
+ */
+
+#ifndef KRB_CONF_DEFS
+#define KRB_CONF_DEFS
+
+/* Byte ordering */
+extern int krbONE;
+#define HOST_BYTE_ORDER (* (char *) &krbONE)
+#define MSB_FIRST 0 /* 68000, IBM RT/PC */
+#define LSB_FIRST 1 /* Vax, PC8086 */
+
+#endif KRB_CONF_DEFS
diff --git a/eBones/include/lsb_addr_comp.h b/eBones/include/lsb_addr_comp.h
new file mode 100644
index 0000000000000..2686ade5481f3
--- /dev/null
+++ b/eBones/include/lsb_addr_comp.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Comparison macros to emulate LSBFIRST comparison results of network
+ * byte-order quantities
+ *
+ * from: lsb_addr_comp.h,v 4.0 89/01/23 15:44:46 jtkohl Exp $
+ * $Id: lsb_addr_comp.h,v 1.3 1995/07/18 16:36:39 mark Exp $
+ */
+
+#ifndef LSB_ADDR_COMP_DEFS
+#define LSB_ADDR_COMP_DEFS
+
+#include "osconf.h"
+
+#ifdef LSBFIRST
+#define lsb_net_ulong_less(x,y) ((x < y) ? -1 : ((x > y) ? 1 : 0))
+#define lsb_net_ushort_less(x,y) ((x < y) ? -1 : ((x > y) ? 1 : 0))
+#else
+/* MSBFIRST */
+#define u_char_comp(x,y) \
+ (((x)>(y))?(1):(((x)==(y))?(0):(-1)))
+/* This is gross, but... */
+#define lsb_net_ulong_less(x, y) long_less_than((u_char *)&x, (u_char *)&y)
+#define lsb_net_ushort_less(x, y) short_less_than((u_char *)&x, (u_char *)&y)
+
+#define long_less_than(x,y) \
+ (u_char_comp((x)[3],(y)[3])?u_char_comp((x)[3],(y)[3]): \
+ (u_char_comp((x)[2],(y)[2])?u_char_comp((x)[2],(y)[2]): \
+ (u_char_comp((x)[1],(y)[1])?u_char_comp((x)[1],(y)[1]): \
+ (u_char_comp((x)[0],(y)[0])))))
+#define short_less_than(x,y) \
+ (u_char_comp((x)[1],(y)[1])?u_char_comp((x)[1],(y)[1]): \
+ (u_char_comp((x)[0],(y)[0])))
+
+#endif /* LSBFIRST */
+
+#endif /* LSB_ADDR_COMP_DEFS */
diff --git a/eBones/include/osconf.h b/eBones/include/osconf.h
new file mode 100644
index 0000000000000..e0af41a9570c7
--- /dev/null
+++ b/eBones/include/osconf.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Athena configuration.
+ *
+ * from: osconf.h,v 4.4 89/12/19 13:26:27 jtkohl Exp $
+ * $Id: osconf.h,v 1.3 1995/07/18 16:36:41 mark Exp $
+ */
+
+#ifdef tahoe
+#include "conf-bsdtahoe.h"
+#else /* !tahoe */
+#ifdef vax
+#include "conf-bsdvax.h"
+#else /* !vax */
+#if defined(mips) && defined(ultrix)
+#include "conf-ultmips2.h"
+#else /* !Ultrix MIPS-2 */
+#ifdef ibm032
+#include "conf-bsdibm032.h"
+#else /* !ibm032 */
+#ifdef apollo
+#include "conf-bsdapollo.h"
+#else /* !apollo */
+#ifdef sun
+#ifdef sparc
+#include "conf-bsdsparc.h"
+#else /* sun but not sparc */
+#ifdef i386
+#include "conf-bsd386i.h"
+#else /* sun but not (sparc or 386i) */
+#include "conf-bsdm68k.h"
+#endif /* i386 */
+#endif /* sparc */
+#else /* !sun */
+#ifdef pyr
+#include "conf-pyr.h"
+#endif /* pyr */
+#endif /* sun */
+#endif /* apollo */
+#endif /* ibm032 */
+#endif /* mips */
+#endif /* vax */
+#endif /* tahoe */
+
+#if defined(__FreeBSD__) && defined(i386)
+#include "conf-bsd386i.h"
+#endif
+
diff --git a/eBones/include/passwd_server.h b/eBones/include/passwd_server.h
new file mode 100644
index 0000000000000..662e65423cd2f
--- /dev/null
+++ b/eBones/include/passwd_server.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Include file for password server
+ *
+ * from: passwd_server.h,v 4.6 89/01/11 15:12:22 steiner Exp $
+ * $Id: passwd_server.h,v 1.3 1995/07/18 16:36:43 mark Exp $
+ */
+
+#ifndef PASSWD_SERVER_DEFS
+#define PASSWD_SERVER_DEFS
+
+#define PW_SRV_VERSION 2 /* version number */
+#define RETRY_LIMIT 1
+#define TIME_OUT 30
+#define USER_TIMEOUT 90
+#define MAX_KPW_LEN 40 /* hey, seems like a good number */
+
+#define INSTALL_NEW_PW (1<<0) /*
+ * ver, cmd, name, password, old_pass,
+ * crypt_pass, uid
+ */
+
+#define INSTALL_REPLY (1<<1) /* ver, cmd, name, password */
+
+#endif /* PASSWD_SERVER_DEFS */
diff --git a/eBones/include/principal.h b/eBones/include/principal.h
new file mode 100644
index 0000000000000..7fa67bc42976d
--- /dev/null
+++ b/eBones/include/principal.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Definitions for principal names.
+ *
+ * from: principal.h,v 4.5 89/01/11 15:15:01 steiner Exp $
+ * $Id: principal.h,v 1.3 1995/07/18 16:36:45 mark Exp $
+ */
+
+#ifndef PRINCIPAL_DEFS
+#define PRINCIPAL_DEFS
+
+#define NAME_LEN 39
+#define INSTANCE_LEN 39
+
+#endif /* PRINCIPAL_DEFS */
diff --git a/eBones/include/prot.h b/eBones/include/prot.h
new file mode 100644
index 0000000000000..ec0ee07dcc9f3
--- /dev/null
+++ b/eBones/include/prot.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ * For copying and distribution information, please see the file
+ * <Copyright.MIT>.
+ *
+ * Include file with authentication protocol information.
+ *
+ * from: prot.h,v 4.13 89/01/24 14:27:22 jtkohl Exp $
+ * $Id: prot.h,v 1.3 1995/07/18 16:36:46 mark Exp $
+ */
+
+#include <krb_conf.h>
+
+#ifndef PROT_DEFS
+#define PROT_DEFS
+
+#define KRB_PORT 750 /* PC's don't have
+ * /etc/services */
+#define KRB_PROT_VERSION 4
+#define MAX_PKT_LEN 1000
+#define MAX_TXT_LEN 1000
+#define TICKET_GRANTING_TICKET "krbtgt"
+
+/* Macro's to obtain various fields from a packet */
+
+#define pkt_version(packet) (unsigned int) *(packet->dat)
+#define pkt_msg_type(packet) (unsigned int) *(packet->dat+1)
+#define pkt_a_name(packet) (packet->dat+2)
+#define pkt_a_inst(packet) \
+ (packet->dat+3+strlen((char *)pkt_a_name(packet)))
+#define pkt_a_realm(packet) \
+ (pkt_a_inst(packet)+1+strlen((char *)pkt_a_inst(packet)))
+
+/* Macro to obtain realm from application request */
+#define apreq_realm(auth) (auth->dat + 3)
+
+#define pkt_time_ws(packet) (char *) \
+ (packet->dat+5+strlen((char *)pkt_a_name(packet)) + \
+ strlen((char *)pkt_a_inst(packet)) + \
+ strlen((char *)pkt_a_realm(packet)))
+
+#define pkt_no_req(packet) (unsigned short) \
+ *(packet->dat+9+strlen((char *)pkt_a_name(packet)) + \
+ strlen((char *)pkt_a_inst(packet)) + \
+ strlen((char *)pkt_a_realm(packet)))
+#define pkt_x_date(packet) (char *) \
+ (packet->dat+10+strlen((char *)pkt_a_name(packet)) + \
+ strlen((char *)pkt_a_inst(packet)) + \
+ strlen((char *)pkt_a_realm(packet)))
+#define pkt_err_code(packet) ( (char *) \
+ (packet->dat+9+strlen((char *)pkt_a_name(packet)) + \
+ strlen((char *)pkt_a_inst(packet)) + \
+ strlen((char *)pkt_a_realm(packet))))
+#define pkt_err_text(packet) \
+ (packet->dat+13+strlen((char *)pkt_a_name(packet)) + \
+ strlen((char *)pkt_a_inst(packet)) + \
+ strlen((char *)pkt_a_realm(packet)))
+
+/* Routines to create and read packets may be found in prot.c */
+
+KTEXT create_auth_reply();
+KTEXT create_death_packet();
+KTEXT pkt_cipher();
+
+/* Message types , always leave lsb for byte order */
+
+#define AUTH_MSG_KDC_REQUEST 1<<1
+#define AUTH_MSG_KDC_REPLY 2<<1
+#define AUTH_MSG_APPL_REQUEST 3<<1
+#define AUTH_MSG_APPL_REQUEST_MUTUAL 4<<1
+#define AUTH_MSG_ERR_REPLY 5<<1
+#define AUTH_MSG_PRIVATE 6<<1
+#define AUTH_MSG_SAFE 7<<1
+#define AUTH_MSG_APPL_ERR 8<<1
+#define AUTH_MSG_DIE 63<<1
+
+/* values for kerb error codes */
+
+#define KERB_ERR_OK 0
+#define KERB_ERR_NAME_EXP 1
+#define KERB_ERR_SERVICE_EXP 2
+#define KERB_ERR_AUTH_EXP 3
+#define KERB_ERR_PKT_VER 4
+#define KERB_ERR_NAME_MAST_KEY_VER 5
+#define KERB_ERR_SERV_MAST_KEY_VER 6
+#define KERB_ERR_BYTE_ORDER 7
+#define KERB_ERR_PRINCIPAL_UNKNOWN 8
+#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9
+#define KERB_ERR_NULL_KEY 10
+
+#endif /* PROT_DEFS */
diff --git a/eBones/lib/libacl/acl_files.doc b/eBones/lib/libacl/acl_files.doc
new file mode 100644
index 0000000000000..4096f9bbb3d38
--- /dev/null
+++ b/eBones/lib/libacl/acl_files.doc
@@ -0,0 +1,107 @@
+PROTOTYPE ACL LIBRARY
+
+Introduction
+
+An access control list (ACL) is a list of principals, where each
+principal is is represented by a text string which cannot contain
+whitespace. The library allows application programs to refer to named
+access control lists to test membership and to atomically add and
+delete principals using a natural and intuitive interface. At
+present, the names of access control lists are required to be Unix
+filenames, and refer to human-readable Unix files; in the future, when
+a networked ACL server is implemented, the names may refer to a
+different namespace specific to the ACL service.
+
+
+Usage
+
+cc <files> -lacl -lkrb.
+
+
+
+Principal Names
+
+Principal names have the form
+
+<name>[.<instance>][@<realm>]
+
+e.g.
+
+asp
+asp.root
+asp@ATHENA.MIT.EDU
+asp.@ATHENA.MIT.EDU
+asp.root@ATHENA.MIT.EDU
+
+It is possible for principals to be underspecified. If instance is
+missing, it is assumed to be "". If realm is missing, it is assumed
+to be local_realm. The canonical form contains all of name, instance,
+and realm; the acl_add and acl_delete routines will always
+leave the file in that form. Note that the canonical form of
+asp@ATHENA.MIT.EDU is actually asp.@ATHENA.MIT.EDU.
+
+
+Routines
+
+acl_canonicalize_principal(principal, buf)
+char *principal;
+char *buf; /*RETVAL*/
+
+Store the canonical form of principal in buf. Buf must contain enough
+space to store a principal, given the limits on the sizes of name,
+instance, and realm specified in /usr/include/krb.h.
+
+acl_check(acl, principal)
+char *acl;
+char *principal;
+
+Returns nonzero if principal appears in acl. Returns 0 if principal
+does not appear in acl, or if an error occurs. Canonicalizes
+principal before checking, and allows the ACL to contain wildcards.
+
+acl_exact_match(acl, principal)
+char *acl;
+char *principal;
+
+Like acl_check, but does no canonicalization or wildcarding.
+
+acl_add(acl, principal)
+char *acl;
+char *principal;
+
+Atomically adds principal to acl. Returns 0 if successful, nonzero
+otherwise. It is considered a failure if principal is already in acl.
+This routine will canonicalize principal, but will treat wildcards
+literally.
+
+acl_delete(acl, principal)
+char *acl;
+char *principal;
+
+Atomically deletes principal from acl. Returns 0 if successful,
+nonzero otherwise. It is consider a failure if principal is not
+already in acl. This routine will canonicalize principal, but will
+treat wildcards literally.
+
+acl_initialize(acl, mode)
+char *acl;
+int mode;
+
+Initialize acl. If acl file does not exist, creates it with mode
+mode. If acl exists, removes all members. Returns 0 if successful,
+nonzero otherwise. WARNING: Mode argument is likely to change with
+the eventual introduction of an ACL service.
+
+
+Known problems
+
+In the presence of concurrency, there is a very small chance that
+acl_add or acl_delete could report success even though it would have
+had no effect. This is a necessary side effect of using lock files
+for concurrency control rather than flock(2), which is not supported
+by NFS.
+
+The current implementation caches ACLs in memory in a hash-table
+format for increased efficiency in checking membership; one effect of
+the caching scheme is that one file descriptor will be kept open for
+each ACL cached, up to a maximum of 8.
diff --git a/eBones/patchlevel.h b/eBones/patchlevel.h
new file mode 100644
index 0000000000000..87e5061c8a8bd
--- /dev/null
+++ b/eBones/patchlevel.h
@@ -0,0 +1,6 @@
+/*-
+ * $Id: patchlevel.h,v 1.3 1995/07/18 16:34:26 mark Exp $
+ */
+
+#define PATCHLEVEL 9
+#define FreeBSD_PL 0.1
diff --git a/eBones/usr.sbin/kdb_edit/kdb_edit.8 b/eBones/usr.sbin/kdb_edit/kdb_edit.8
new file mode 100644
index 0000000000000..44a0fa61ed70d
--- /dev/null
+++ b/eBones/usr.sbin/kdb_edit/kdb_edit.8
@@ -0,0 +1,58 @@
+.\" from: kdb_edit.8,v 4.1 89/01/23 11:08:55 jtkohl Exp $
+.\" $Id: kdb_edit.8,v 1.2 1995/02/08 10:54:20 jkh Exp $
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <Copyright.MIT>.
+.\"
+.TH KDB_EDIT 8 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kdb_edit \- Kerberos key distribution center database editing utility
+.SH SYNOPSIS
+kdb_edit [
+.B \-n
+]
+.SH DESCRIPTION
+.I kdb_edit
+is used to create or change principals stored in the Kerberos key
+distribution center (KDC) database.
+.PP
+When executed,
+.I kdb_edit
+prompts for the master key string and verifies that it matches the
+master key stored in the database.
+If the
+.B \-n
+option is specified, the master key is instead fetched from the master
+key cache file.
+.PP
+Once the master key has been verified,
+.I kdb_edit
+begins a prompt loop. The user is prompted for the principal and
+instance to be modified. If the entry is not found the user may create
+it.
+Once an entry is found or created, the user may set the password,
+expiration date, maximum ticket lifetime, and attributes.
+Default expiration dates, maximum ticket lifetimes, and attributes are
+presented in brackets; if the user presses return the default is selected.
+There is no default password.
+The password "RANDOM" and an empty password are interpreted specially,
+if entered the user may have the program select a random DES key for the
+principal.
+.PP
+Upon successfully creating or changing the entry, ``Edit O.K.'' is
+printed.
+.SH DIAGNOSTICS
+.TP 20n
+"verify_master_key: Invalid master key, does not match database."
+The master key string entered was incorrect.
+.SH FILES
+.TP 20n
+/etc/kerberosIV/principal.db
+DBM file containing database
+.TP
+/etc/kerberosIV/principal.ok
+Semaphore indicating that the DBM database is not being modified.
+.TP
+/etc/kerberosIV/master_key
+Master key cache file.
diff --git a/eBones/usr.sbin/kdb_edit/time.h b/eBones/usr.sbin/kdb_edit/time.h
new file mode 100644
index 0000000000000..ae84e2e24585e
--- /dev/null
+++ b/eBones/usr.sbin/kdb_edit/time.h
@@ -0,0 +1,45 @@
+/* Structure for use by time manipulating subroutines.
+ * The following library routines use it:
+ * libc: ctime, localtime, gmtime, asctime
+ * libcx: partime, maketime (may not be installed yet)
+ */
+
+/*
+ * from: time.h,v 1.1 82/05/06 11:34:29 wft Exp $
+ * $Id: time.h,v 1.3 1995/07/18 16:37:31 mark Exp $
+ */
+
+struct tm { /* See defines below for allowable ranges */
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_wday;
+ int tm_yday;
+ int tm_isdst;
+ int tm_zon; /* NEW: mins westward of Greenwich */
+ int tm_ampm; /* NEW: 1 if AM, 2 if PM */
+};
+
+#define LCLZONE (5*60) /* Until V7 ftime(2) works, this defines local zone*/
+#define TMNULL (-1) /* Items not specified are given this value
+ * in order to distinguish null specs from zero
+ * specs. This is only used by partime and
+ * maketime. */
+
+ /* Indices into TM structure */
+#define TM_SEC 0 /* 0-59 */
+#define TM_MIN 1 /* 0-59 */
+#define TM_HOUR 2 /* 0-23 */
+#define TM_MDAY 3 /* 1-31 day of month */
+#define TM_DAY TM_MDAY /* " synonym */
+#define TM_MON 4 /* 0-11 */
+#define TM_YEAR 5 /* (year-1900) (year) */
+#define TM_WDAY 6 /* 0-6 day of week (0 = Sunday) */
+#define TM_YDAY 7 /* 0-365 day of year */
+#define TM_ISDST 8 /* 0 Std, 1 DST */
+ /* New stuff */
+#define TM_ZON 9 /* 0-(24*60) minutes west of Greenwich */
+#define TM_AMPM 10 /* 1 AM, 2 PM */
diff --git a/gnu/libexec/uucp/libunix/failed.c b/gnu/libexec/uucp/libunix/failed.c
new file mode 100644
index 0000000000000..66c98a80df69e
--- /dev/null
+++ b/gnu/libexec/uucp/libunix/failed.c
@@ -0,0 +1,26 @@
+/* failed.c
+ Save a file in the .Failed directory. */
+
+#include "uucp.h"
+
+#include "sysdep.h"
+#include "uudefs.h"
+#include "system.h"
+
+char *
+zsysdep_save_failed_file (zfile)
+ const char *zfile;
+{
+ char *zto;
+
+ zto = zsappend3 (zSspooldir, FAILEDDIR, zfile);
+
+ if (! fsysdep_move_file (zfile, zto, TRUE, FALSE, FALSE,
+ (const char *) NULL))
+ {
+ ubuffree (zto);
+ return NULL;
+ }
+
+ return zto;
+}
diff --git a/gnu/libexec/uucp/libunix/sync.c b/gnu/libexec/uucp/libunix/sync.c
new file mode 100644
index 0000000000000..c346c58ccb7ad
--- /dev/null
+++ b/gnu/libexec/uucp/libunix/sync.c
@@ -0,0 +1,42 @@
+/* sync.c
+ Sync a file to disk, if FSYNC_ON_CLOSE is set. */
+
+#include "uucp.h"
+
+#include "uudefs.h"
+#include "sysdep.h"
+#include "system.h"
+
+#include <errno.h>
+
+boolean
+fsysdep_sync (e, zmsg)
+ openfile_t e;
+ const char *zmsg;
+{
+ int o;
+
+#if USE_STDIO
+ if (fflush (e) == EOF)
+ {
+ ulog (LOG_ERROR, "%s: fflush: %s", zmsg, strerror (errno));
+ return FALSE;
+ }
+#endif
+
+#if USE_STDIO
+ o = fileno (e);
+#else
+ o = e;
+#endif
+
+#if FSYNC_ON_CLOSE
+ if (fsync (o) < 0)
+ {
+ ulog (LOG_ERROR, "%s: fsync: %s", zmsg, strerror (errno));
+ return FALSE;
+ }
+#endif
+
+ return TRUE;
+}
diff --git a/gnu/libexec/uucp/libunix/tcp.c b/gnu/libexec/uucp/libunix/tcp.c
new file mode 100644
index 0000000000000..6ec39f26a63ba
--- /dev/null
+++ b/gnu/libexec/uucp/libunix/tcp.c
@@ -0,0 +1,444 @@
+/* tcp.c
+ Code to handle TCP connections.
+
+ Copyright (C) 1991, 1992, 1993, 1995 Ian Lance Taylor
+
+ This file is part of the Taylor UUCP package.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The author of the program may be contacted at ian@airs.com or
+ c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
+ */
+
+#include "uucp.h"
+
+#if USE_RCS_ID
+const char tcp_rcsid[] = "$Id: tcp.c,v 1.5 1995/06/21 19:20:46 ian Rel $";
+#endif
+
+#if HAVE_TCP
+
+#include "uudefs.h"
+#include "uuconf.h"
+#include "sysdep.h"
+#include "conn.h"
+#include "system.h"
+
+#include <errno.h>
+
+#if HAVE_SYS_TYPES_TCP_H
+#include <sys/types.tcp.h>
+#endif
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#if HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#endif
+
+#ifndef FD_CLOEXEC
+#define FD_CLOEXEC 1
+#endif
+
+/* This code handles TCP connections. It assumes a Berkeley socket
+ interface. */
+
+/* The normal "uucp" port number. */
+#define IUUCP_PORT (540)
+
+/* Local functions. */
+static void utcp_free P((struct sconnection *qconn));
+static boolean ftcp_open P((struct sconnection *qconn, long ibaud,
+ boolean fwait));
+static boolean ftcp_close P((struct sconnection *qconn,
+ pointer puuconf,
+ struct uuconf_dialer *qdialer,
+ boolean fsuccess));
+static boolean ftcp_dial P((struct sconnection *qconn, pointer puuconf,
+ const struct uuconf_system *qsys,
+ const char *zphone,
+ struct uuconf_dialer *qdialer,
+ enum tdialerfound *ptdialer));
+static int itcp_port_number P((const char *zport));
+
+/* The command table for a TCP connection. */
+static const struct sconncmds stcpcmds =
+{
+ utcp_free,
+ NULL, /* pflock */
+ NULL, /* pfunlock */
+ ftcp_open,
+ ftcp_close,
+ ftcp_dial,
+ fsysdep_conn_read,
+ fsysdep_conn_write,
+ fsysdep_conn_io,
+ NULL, /* pfbreak */
+ NULL, /* pfset */
+ NULL, /* pfcarrier */
+ fsysdep_conn_chat,
+ NULL /* pibaud */
+};
+
+/* Initialize a TCP connection. */
+
+boolean
+fsysdep_tcp_init (qconn)
+ struct sconnection *qconn;
+{
+ struct ssysdep_conn *q;
+
+ q = (struct ssysdep_conn *) xmalloc (sizeof (struct ssysdep_conn));
+ q->o = -1;
+ q->ord = -1;
+ q->owr = -1;
+ q->zdevice = NULL;
+ q->iflags = -1;
+ q->iwr_flags = -1;
+ q->fterminal = FALSE;
+ q->ftli = FALSE;
+ q->ibaud = 0;
+
+ qconn->psysdep = (pointer) q;
+ qconn->qcmds = &stcpcmds;
+ return TRUE;
+}
+
+/* Free a TCP connection. */
+
+static void
+utcp_free (qconn)
+ struct sconnection *qconn;
+{
+ xfree (qconn->psysdep);
+}
+
+/* Open a TCP connection. If the fwait argument is TRUE, we are
+ running as a server. Otherwise we are just trying to reach another
+ system. */
+
+static boolean
+ftcp_open (qconn, ibaud, fwait)
+ struct sconnection *qconn;
+ long ibaud;
+ boolean fwait;
+{
+ struct ssysdep_conn *qsysdep;
+ struct sockaddr_in s;
+ const char *zport;
+ uid_t ieuid;
+ boolean fswap;
+
+ ulog_device ("TCP");
+
+ qsysdep = (struct ssysdep_conn *) qconn->psysdep;
+
+ qsysdep->o = socket (AF_INET, SOCK_STREAM, 0);
+ if (qsysdep->o < 0)
+ {
+ ulog (LOG_ERROR, "socket: %s", strerror (errno));
+ return FALSE;
+ }
+
+ if (fcntl (qsysdep->o, F_SETFD,
+ fcntl (qsysdep->o, F_GETFD, 0) | FD_CLOEXEC) < 0)
+ {
+ ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno));
+ (void) close (qsysdep->o);
+ qsysdep->o = -1;
+ return FALSE;
+ }
+
+ qsysdep->iflags = fcntl (qsysdep->o, F_GETFL, 0);
+ if (qsysdep->iflags < 0)
+ {
+ ulog (LOG_ERROR, "fcntl: %s", strerror (errno));
+ (void) close (qsysdep->o);
+ qsysdep->o = -1;
+ return FALSE;
+ }
+
+ /* We save our process ID in the qconn structure. This is checked
+ in ftcp_close. */
+ qsysdep->ipid = getpid ();
+
+ /* If we aren't waiting for a connection, we're done. */
+ if (! fwait)
+ return TRUE;
+
+ /* Run as a server and wait for a new connection. The code in
+ uucico.c has already detached us from our controlling terminal.
+ From this point on if the server gets an error we exit; we only
+ return if we have received a connection. It would be more robust
+ to respawn the server if it fails; someday. */
+ bzero ((pointer) &s, sizeof s);
+ s.sin_family = AF_INET;
+ zport = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zport;
+ s.sin_port = itcp_port_number (zport);
+ s.sin_addr.s_addr = htonl (INADDR_ANY);
+
+ /* Swap to our real user ID when doing the bind call. This will
+ permit the server to use privileged TCP ports when invoked by
+ root. We only swap if our effective user ID is not root, so that
+ the program can also be made suid root in order to get privileged
+ ports when invoked by anybody. */
+ fswap = geteuid () != 0;
+ if (fswap)
+ {
+ if (! fsuser_perms (&ieuid))
+ {
+ (void) close (qsysdep->o);
+ qsysdep->o = -1;
+ return FALSE;
+ }
+ }
+
+ if (bind (qsysdep->o, (struct sockaddr *) &s, sizeof s) < 0)
+ {
+ if (fswap)
+ (void) fsuucp_perms ((long) ieuid);
+ ulog (LOG_FATAL, "bind: %s", strerror (errno));
+ }
+
+ /* Now swap back to the uucp user ID. */
+ if (fswap)
+ {
+ if (! fsuucp_perms ((long) ieuid))
+ ulog (LOG_FATAL, "Could not swap back to UUCP user permissions");
+ }
+
+ if (listen (qsysdep->o, 5) < 0)
+ ulog (LOG_FATAL, "listen: %s", strerror (errno));
+
+ while (! FGOT_SIGNAL ())
+ {
+ size_t clen;
+ int onew;
+ pid_t ipid;
+
+ DEBUG_MESSAGE0 (DEBUG_PORT,
+ "ftcp_open: Waiting for connections");
+
+ clen = sizeof s;
+ onew = accept (qsysdep->o, (struct sockaddr *) &s, &clen);
+ if (onew < 0)
+ ulog (LOG_FATAL, "accept: %s", strerror (errno));
+
+ DEBUG_MESSAGE0 (DEBUG_PORT,
+ "ftcp_open: Got connection; forking");
+
+ ipid = ixsfork ();
+ if (ipid < 0)
+ ulog (LOG_FATAL, "fork: %s", strerror (errno));
+ if (ipid == 0)
+ {
+ (void) close (qsysdep->o);
+ qsysdep->o = onew;
+
+ /* Now we fork and let our parent die, so that we become
+ a child of init. This lets the main server code wait
+ for its child and then continue without accumulating
+ zombie children. */
+ ipid = ixsfork ();
+ if (ipid < 0)
+ {
+ ulog (LOG_ERROR, "fork: %s", strerror (errno));
+ _exit (EXIT_FAILURE);
+ }
+
+ if (ipid != 0)
+ _exit (EXIT_SUCCESS);
+
+ ulog_id (getpid ());
+
+ return TRUE;
+ }
+
+ (void) close (onew);
+
+ /* Now wait for the child. */
+ (void) ixswait ((unsigned long) ipid, (const char *) NULL);
+ }
+
+ /* We got a signal. */
+ usysdep_exit (FALSE);
+
+ /* Avoid compiler warnings. */
+ return FALSE;
+}
+
+/* Close the port. */
+
+/*ARGSUSED*/
+static boolean
+ftcp_close (qconn, puuconf, qdialer, fsuccess)
+ struct sconnection *qconn;
+ pointer puuconf;
+ struct uuconf_dialer *qdialer;
+ boolean fsuccess;
+{
+ struct ssysdep_conn *qsysdep;
+ boolean fret;
+
+ qsysdep = (struct ssysdep_conn *) qconn->psysdep;
+ fret = TRUE;
+ if (qsysdep->o >= 0 && close (qsysdep->o) < 0)
+ {
+ ulog (LOG_ERROR, "close: %s", strerror (errno));
+ fret = FALSE;
+ }
+ qsysdep->o = -1;
+
+ /* If the current pid is not the one we used to open the port, then
+ we must have forked up above and we are now the child. In this
+ case, we are being called from within the fendless loop in
+ uucico.c. We return FALSE to force the loop to end and the child
+ to exit. This should be handled in a cleaner fashion. */
+ if (qsysdep->ipid != getpid ())
+ fret = FALSE;
+
+ return fret;
+}
+
+/* Dial out on a TCP port, so to speak: connect to a remote computer. */
+
+/*ARGSUSED*/
+static boolean
+ftcp_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialer)
+ struct sconnection *qconn;
+ pointer puuconf;
+ const struct uuconf_system *qsys;
+ const char *zphone;
+ struct uuconf_dialer *qdialer;
+ enum tdialerfound *ptdialer;
+{
+ struct ssysdep_conn *qsysdep;
+ const char *zhost;
+ struct hostent *q;
+ struct sockaddr_in s;
+ const char *zport;
+ char **pzdialer;
+
+ qsysdep = (struct ssysdep_conn *) qconn->psysdep;
+
+ *ptdialer = DIALERFOUND_FALSE;
+
+ zhost = zphone;
+ if (zhost == NULL)
+ {
+ if (qsys == NULL)
+ {
+ ulog (LOG_ERROR, "No address for TCP connection");
+ return FALSE;
+ }
+ zhost = qsys->uuconf_zname;
+ }
+
+ errno = 0;
+ q = gethostbyname ((char *) zhost);
+ if (q != NULL)
+ {
+ s.sin_family = q->h_addrtype;
+ memcpy (&s.sin_addr.s_addr, q->h_addr, (size_t) q->h_length);
+ }
+ else
+ {
+ if (errno != 0)
+ {
+ ulog (LOG_ERROR, "gethostbyname (%s): %s", zhost, strerror (errno));
+ return FALSE;
+ }
+
+ s.sin_family = AF_INET;
+ s.sin_addr.s_addr = inet_addr ((char *) zhost);
+ if ((long) s.sin_addr.s_addr == (long) -1)
+ {
+ ulog (LOG_ERROR, "%s: unknown host name", zhost);
+ return FALSE;
+ }
+ }
+
+ zport = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zport;
+ s.sin_port = itcp_port_number (zport);
+
+ if (connect (qsysdep->o, (struct sockaddr *) &s, sizeof s) < 0)
+ {
+ ulog (LOG_ERROR, "connect: %s", strerror (errno));
+ return FALSE;
+ }
+
+ /* Handle the dialer sequence, if any. */
+ pzdialer = qconn->qport->uuconf_u.uuconf_stcp.uuconf_pzdialer;
+ if (pzdialer != NULL && *pzdialer != NULL)
+ {
+ if (! fconn_dial_sequence (qconn, puuconf, pzdialer, qsys, zphone,
+ qdialer, ptdialer))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Get the port number given a name. The argument will almost always
+ be "uucp" so we cache that value. The return value is always in
+ network byte order. This returns -1 on error. */
+
+static int
+itcp_port_number (zname)
+ const char *zname;
+{
+ boolean fuucp;
+ static int iuucp;
+ int i;
+ char *zend;
+ struct servent *q;
+
+ fuucp = strcmp (zname, "uucp") == 0;
+ if (fuucp && iuucp != 0)
+ return iuucp;
+
+ /* Try it as a number first. */
+ i = strtol ((char *) zname, &zend, 10);
+ if (i != 0 && *zend == '\0')
+ return htons (i);
+
+ q = getservbyname ((char *) zname, (char *) "tcp");
+ if (q == NULL)
+ {
+ /* We know that the "uucp" service should be 540, even if isn't
+ in /etc/services. */
+ if (fuucp)
+ {
+ iuucp = htons (IUUCP_PORT);
+ return iuucp;
+ }
+ ulog (LOG_ERROR, "getservbyname (%s): %s", zname, strerror (errno));
+ return -1;
+ }
+
+ if (fuucp)
+ iuucp = q->s_port;
+
+ return q->s_port;
+}
+
+#endif /* HAVE_TCP */
diff --git a/gnu/libexec/uucp/libunix/tli.c b/gnu/libexec/uucp/libunix/tli.c
new file mode 100644
index 0000000000000..3e546c844991b
--- /dev/null
+++ b/gnu/libexec/uucp/libunix/tli.c
@@ -0,0 +1,628 @@
+/* tli.c
+ Code to handle TLI connections.
+
+ Copyright (C) 1992, 1993, 1994 Ian Lance Taylor
+
+ This file is part of the Taylor UUCP package.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The author of the program may be contacted at ian@airs.com or
+ c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
+ */
+
+#include "uucp.h"
+
+#if USE_RCS_ID
+const char tli_rcsid[] = "$Id: tli.c,v 1.4 1995/06/21 19:20:50 ian Rel $";
+#endif
+
+#if HAVE_TLI
+
+#include "sysdep.h"
+#include "uudefs.h"
+#include "uuconf.h"
+#include "conn.h"
+#include "system.h"
+
+#include <errno.h>
+
+#if HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#if HAVE_TIUSER_H
+#include <tiuser.h>
+#else
+#if HAVE_XTI_H
+#include <xti.h>
+#else
+#if HAVE_SYS_TLI_H
+#include <sys/tli.h>
+#endif
+#endif
+#endif
+
+#if HAVE_STROPTS_H
+#include <stropts.h>
+#endif
+
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#if HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#endif
+
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#define O_WRONLY 1
+#define O_RDWR 2
+#endif
+
+#ifndef FD_CLOEXEC
+#define FD_CLOEXEC 1
+#endif
+
+/* The arguments to t_alloca have two different names. I want the
+ SVID ones, not the XPG3 ones. */
+#ifndef T_BIND
+#define T_BIND T_BIND_STR
+#endif
+#ifndef T_CALL
+#define T_CALL T_CALL_STR
+#endif
+
+/* Hopefully these externs will not cause any trouble. This is how
+ they are shown in the SVID. */
+extern int t_errno;
+extern char *t_errlist[];
+extern int t_nerr;
+
+#ifndef HAVE_TIUSER_H
+#ifndef t_alloc
+extern pointer t_alloc ();
+#endif
+#endif
+
+/* This code handles TLI connections. It's Unix specific. It's
+ largely based on code from Unix Network Programming, by W. Richard
+ Stevens. */
+
+/* Local functions. */
+static const char *ztlierror P((void));
+static void utli_free P((struct sconnection *qconn));
+static boolean ftli_push P((struct sconnection *qconn));
+static boolean ftli_open P((struct sconnection *qconn, long ibaud,
+ boolean fwait));
+static boolean ftli_close P((struct sconnection *qconn,
+ pointer puuconf,
+ struct uuconf_dialer *qdialer,
+ boolean fsuccess));
+static boolean ftli_dial P((struct sconnection *qconn, pointer puuconf,
+ const struct uuconf_system *qsys,
+ const char *zphone,
+ struct uuconf_dialer *qdialer,
+ enum tdialerfound *ptdialer));
+
+/* The command table for a TLI connection. */
+static const struct sconncmds stlicmds =
+{
+ utli_free,
+ NULL, /* pflock */
+ NULL, /* pfunlock */
+ ftli_open,
+ ftli_close,
+ ftli_dial,
+ fsysdep_conn_read,
+ fsysdep_conn_write,
+ fsysdep_conn_io,
+ NULL, /* pfbreak */
+ NULL, /* pfset */
+ NULL, /* pfcarrier */
+ fsysdep_conn_chat,
+ NULL /* pibaud */
+};
+
+/* Get a TLI error string. */
+
+static const char *
+ztlierror ()
+{
+ if (t_errno == TSYSERR)
+ return strerror (errno);
+ if (t_errno < 0 || t_errno >= t_nerr)
+ return "Unknown TLI error";
+ return t_errlist[t_errno];
+}
+
+/* Initialize a TLI connection. This may be called with qconn->qport
+ NULL, when opening standard input as a TLI connection. */
+
+boolean
+fsysdep_tli_init (qconn)
+ struct sconnection *qconn;
+{
+ struct ssysdep_conn *q;
+
+ q = (struct ssysdep_conn *) xmalloc (sizeof (struct ssysdep_conn));
+ q->o = -1;
+ q->ord = -1;
+ q->owr = -1;
+ q->zdevice = NULL;
+ q->iflags = -1;
+ q->iwr_flags = -1;
+ q->fterminal = FALSE;
+ q->ftli = TRUE;
+ q->ibaud = 0;
+
+ qconn->psysdep = (pointer) q;
+ qconn->qcmds = &stlicmds;
+ return TRUE;
+}
+
+/* Free a TLI connection. */
+
+static void
+utli_free (qconn)
+ struct sconnection *qconn;
+{
+ xfree (qconn->psysdep);
+}
+
+/* Push all desired modules onto a TLI stream. If the user requests a
+ STREAMS connection without giving a list of modules, we just push
+ tirdwr. If the I_PUSH ioctl is not defined on this system, we just
+ ignore any list of modules. */
+
+static boolean
+ftli_push (qconn)
+ struct sconnection *qconn;
+{
+#ifdef I_PUSH
+
+ struct ssysdep_conn *qsysdep;
+
+ qsysdep = (struct ssysdep_conn *) qconn->psysdep;
+
+ if (qconn->qport->uuconf_u.uuconf_stli.uuconf_pzpush != NULL)
+ {
+ char **pz;
+
+ for (pz = qconn->qport->uuconf_u.uuconf_stli.uuconf_pzpush;
+ *pz != NULL;
+ pz++)
+ {
+ if (ioctl (qsysdep->o, I_PUSH, *pz) < 0)
+ {
+ ulog (LOG_ERROR, "ioctl (I_PUSH, %s): %s", *pz,
+ strerror (errno));
+ return FALSE;
+ }
+ }
+ }
+ else if (qconn->qport->uuconf_u.uuconf_stli.uuconf_fstream)
+ {
+ if (ioctl (qsysdep->o, I_PUSH, "tirdwr") < 0)
+ {
+ ulog (LOG_ERROR, "ioctl (I_PUSH, tirdwr): %s",
+ strerror (errno));
+ return FALSE;
+ }
+ }
+
+ /* If we have just put the connection into stream mode, we must turn
+ off the TLI flag to avoid using TLI calls on it. */
+ if (qconn->qport->uuconf_u.uuconf_stli.uuconf_fstream)
+ qsysdep->ftli = FALSE;
+
+#endif /* defined (I_PUSH) */
+
+ return TRUE;
+}
+
+/* Open a TLI connection. If the fwait argument is TRUE, we are
+ running as a server. Otherwise we are just trying to reach another
+ system. */
+
+static boolean
+ftli_open (qconn, ibaud, fwait)
+ struct sconnection *qconn;
+ long ibaud;
+ boolean fwait;
+{
+ struct ssysdep_conn *qsysdep;
+ const char *zdevice;
+ char *zfreedev;
+ const char *zservaddr;
+ char *zfreeaddr;
+ uid_t ieuid;
+ boolean fswap;
+ struct t_bind *qtbind;
+ struct t_call *qtcall;
+
+ /* Unlike most other device types, we don't bother to call
+ ulog_device here, because fconn_open calls it with the name of
+ the port anyhow. */
+
+ qsysdep = (struct ssysdep_conn *) qconn->psysdep;
+
+ zdevice = qconn->qport->uuconf_u.uuconf_stli.uuconf_zdevice;
+ if (zdevice == NULL)
+ zdevice = qconn->qport->uuconf_zname;
+
+ zfreedev = NULL;
+ if (*zdevice != '/')
+ {
+ zfreedev = zbufalc (sizeof "/dev/" + strlen (zdevice));
+ sprintf (zfreedev, "/dev/%s", zdevice);
+ zdevice = zfreedev;
+ }
+
+ /* If we are acting as a server, swap to our real user ID before
+ calling t_open. This will permit the server to use privileged
+ TCP ports when invoked by root. We only swap if our effective
+ user ID is not root, so that the program can also be made suid
+ root in order to get privileged ports when invoked by anybody. */
+ fswap = fwait && geteuid () != 0;
+ if (fswap)
+ {
+ if (! fsuser_perms (&ieuid))
+ {
+ ubuffree (zfreedev);
+ return FALSE;
+ }
+ }
+
+ qsysdep->o = t_open (zdevice, O_RDWR, (struct t_info *) NULL);
+ if (qsysdep->o < 0)
+ {
+ if (fswap)
+ (void) fsuucp_perms ((long) ieuid);
+ ulog (LOG_ERROR, "t_open (%s): %s", zdevice, ztlierror ());
+ ubuffree (zfreedev);
+ return FALSE;
+ }
+
+ if (fcntl (qsysdep->o, F_SETFD,
+ fcntl (qsysdep->o, F_GETFD, 0) | FD_CLOEXEC) < 0)
+ {
+ if (fswap)
+ (void) fsuucp_perms ((long) ieuid);
+ ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno));
+ ubuffree (zfreedev);
+ (void) t_close (qsysdep->o);
+ qsysdep->o = -1;
+ return FALSE;
+ }
+
+ qsysdep->iflags = fcntl (qsysdep->o, F_GETFL, 0);
+ if (qsysdep->iflags < 0)
+ {
+ if (fswap)
+ (void) fsuucp_perms ((long) ieuid);
+ ulog (LOG_ERROR, "fcntl: %s", strerror (errno));
+ ubuffree (zfreedev);
+ (void) t_close (qsysdep->o);
+ qsysdep->o = -1;
+ return FALSE;
+ }
+
+ /* We save our process ID in the qconn structure. This is checked
+ in ftli_close. */
+ qsysdep->ipid = getpid ();
+
+ /* If we aren't waiting for a connection, we can bind to any local
+ address, and then we're finished. */
+ if (! fwait)
+ {
+ /* fswap is known to be FALSE here. */
+ ubuffree (zfreedev);
+ if (t_bind (qsysdep->o, (struct t_bind *) NULL,
+ (struct t_bind *) NULL) < 0)
+ {
+ ulog (LOG_ERROR, "t_bind: %s", ztlierror ());
+ (void) t_close (qsysdep->o);
+ qsysdep->o = -1;
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ /* Run as a server and wait for a new connection. The code in
+ uucico.c has already detached us from our controlling terminal.
+ From this point on if the server gets an error we exit; we only
+ return if we have received a connection. It would be more robust
+ to respawn the server if it fails; someday. */
+ qtbind = (struct t_bind *) t_alloc (qsysdep->o, T_BIND, T_ALL);
+ if (qtbind == NULL)
+ {
+ if (fswap)
+ (void) fsuucp_perms ((long) ieuid);
+ ulog (LOG_FATAL, "t_alloc (T_BIND): %s", ztlierror ());
+ }
+
+ zservaddr = qconn->qport->uuconf_u.uuconf_stli.uuconf_zservaddr;
+ if (zservaddr == NULL)
+ {
+ if (fswap)
+ (void) fsuucp_perms ((long) ieuid);
+ ulog (LOG_FATAL, "Can't run as TLI server; no server address");
+ }
+
+ zfreeaddr = zbufcpy (zservaddr);
+ qtbind->addr.len = cescape (zfreeaddr);
+ if (qtbind->addr.len > qtbind->addr.maxlen)
+ {
+ if (fswap)
+ (void) fsuucp_perms ((long) ieuid);
+ ulog (LOG_FATAL, "%s: TLI server address too long (max %d)",
+ zservaddr, qtbind->addr.maxlen);
+ }
+ memcpy (qtbind->addr.buf, zfreeaddr, qtbind->addr.len);
+ ubuffree (zfreeaddr);
+
+ qtbind->qlen = 5;
+
+ if (t_bind (qsysdep->o, qtbind, (struct t_bind *) NULL) < 0)
+ {
+ if (fswap)
+ (void) fsuucp_perms ((long) ieuid);
+ ulog (LOG_FATAL, "t_bind (%s): %s", zservaddr, ztlierror ());
+ }
+
+ if (fswap)
+ {
+ if (! fsuucp_perms ((long) ieuid))
+ ulog (LOG_FATAL, "Could not swap back to UUCP user permissions");
+ }
+
+ (void) t_free ((pointer) qtbind, T_BIND);
+
+ qtcall = (struct t_call *) t_alloc (qsysdep->o, T_CALL, T_ALL);
+ if (qtcall == NULL)
+ ulog (LOG_FATAL, "t_alloc (T_CALL): %s", ztlierror ());
+
+ while (! FGOT_SIGNAL ())
+ {
+ int onew;
+ pid_t ipid;
+
+ DEBUG_MESSAGE0 (DEBUG_PORT,
+ "ftli_open: Waiting for connections");
+
+ if (t_listen (qsysdep->o, qtcall) < 0)
+ ulog (LOG_FATAL, "t_listen: %s", ztlierror ());
+
+ onew = t_open (zdevice, O_RDWR, (struct t_info *) NULL);
+ if (onew < 0)
+ ulog (LOG_FATAL, "t_open (%s): %s", zdevice, ztlierror ());
+
+ if (fcntl (onew, F_SETFD,
+ fcntl (onew, F_GETFD, 0) | FD_CLOEXEC) < 0)
+ ulog (LOG_FATAL, "fcntl (FD_CLOEXEC): %s", strerror (errno));
+
+ if (t_bind (onew, (struct t_bind *) NULL, (struct t_bind *) NULL) < 0)
+ ulog (LOG_FATAL, "t_bind: %s", ztlierror ());
+
+ if (t_accept (qsysdep->o, onew, qtcall) < 0)
+ {
+ /* We may have received a disconnect. */
+ if (t_errno != TLOOK)
+ ulog (LOG_FATAL, "t_accept: %s", ztlierror ());
+ if (t_rcvdis (qsysdep->o, (struct t_discon *) NULL) < 0)
+ ulog (LOG_FATAL, "t_rcvdis: %s", ztlierror ());
+ (void) t_close (onew);
+ continue;
+ }
+
+ DEBUG_MESSAGE0 (DEBUG_PORT,
+ "ftli_open: Got connection; forking");
+
+ ipid = ixsfork ();
+ if (ipid < 0)
+ ulog (LOG_FATAL, "fork: %s", strerror (errno));
+ if (ipid == 0)
+ {
+ ulog_close ();
+
+ (void) t_close (qsysdep->o);
+ qsysdep->o = onew;
+
+ /* Push any desired modules. */
+ if (! ftli_push (qconn))
+ _exit (EXIT_FAILURE);
+
+ /* Now we fork and let our parent die, so that we become
+ a child of init. This lets the main server code wait
+ for its child and then continue without accumulating
+ zombie children. */
+ ipid = ixsfork ();
+ if (ipid < 0)
+ {
+ ulog (LOG_ERROR, "fork: %s", strerror (errno));
+ _exit (EXIT_FAILURE);
+ }
+
+ if (ipid != 0)
+ _exit (EXIT_SUCCESS);
+
+ ulog_id (getpid ());
+
+ return TRUE;
+ }
+
+ (void) t_close (onew);
+
+ /* Now wait for the child. */
+ (void) ixswait ((unsigned long) ipid, (const char *) NULL);
+ }
+
+ /* We got a signal. */
+ usysdep_exit (FALSE);
+
+ /* Avoid compiler warnings. */
+ return FALSE;
+}
+
+/* Close the port. */
+
+/*ARGSUSED*/
+static boolean
+ftli_close (qconn, puuconf, qdialer, fsuccess)
+ struct sconnection *qconn;
+ pointer puuconf;
+ struct uuconf_dialer *qdialer;
+ boolean fsuccess;
+{
+ struct ssysdep_conn *qsysdep;
+ boolean fret;
+
+ qsysdep = (struct ssysdep_conn *) qconn->psysdep;
+
+ fret = TRUE;
+ if (qsysdep->o >= 0)
+ {
+ if (qsysdep->ftli)
+ {
+ if (t_close (qsysdep->o) < 0)
+ {
+ ulog (LOG_ERROR, "t_close: %s", ztlierror ());
+ fret = FALSE;
+ }
+ }
+ else
+ {
+ if (close (qsysdep->o) < 0)
+ {
+ ulog (LOG_ERROR, "close: %s", strerror (errno));
+ fret = FALSE;
+ }
+ }
+
+ qsysdep->o = -1;
+ }
+
+ /* If the current pid is not the one we used to open the port, then
+ we must have forked up above and we are now the child. In this
+ case, we are being called from within the fendless loop in
+ uucico.c. We return FALSE to force the loop to end and the child
+ to exit. This should be handled in a cleaner fashion. */
+ if (qsysdep->ipid != getpid ())
+ fret = FALSE;
+
+ return fret;
+}
+
+/* Dial out on a TLI port, so to speak: connect to a remote computer. */
+
+/*ARGSUSED*/
+static boolean
+ftli_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound)
+ struct sconnection *qconn;
+ pointer puuconf;
+ const struct uuconf_system *qsys;
+ const char *zphone;
+ struct uuconf_dialer *qdialer;
+ enum tdialerfound *ptdialerfound;
+{
+ struct ssysdep_conn *qsysdep;
+ char **pzdialer;
+ const char *zaddr;
+ struct t_call *qtcall;
+ char *zescape;
+
+ qsysdep = (struct ssysdep_conn *) qconn->psysdep;
+
+ *ptdialerfound = DIALERFOUND_FALSE;
+
+ pzdialer = qconn->qport->uuconf_u.uuconf_stli.uuconf_pzdialer;
+ if (*pzdialer == NULL)
+ pzdialer = NULL;
+
+ /* If the first dialer is "TLI" or "TLIS", we use the first token
+ (pzdialer[1]) as the address to connect to. */
+ zaddr = zphone;
+ if (pzdialer != NULL
+ && (strcmp (pzdialer[0], "TLI") == 0
+ || strcmp (pzdialer[0], "TLIS") == 0))
+ {
+ if (pzdialer[1] == NULL)
+ ++pzdialer;
+ else
+ {
+ if (strcmp (pzdialer[1], "\\D") != 0
+ && strcmp (pzdialer[1], "\\T") != 0)
+ zaddr = pzdialer[1];
+ pzdialer += 2;
+ }
+ }
+
+ if (zaddr == NULL)
+ {
+ ulog (LOG_ERROR, "No address for TLI connection");
+ return FALSE;
+ }
+
+ qtcall = (struct t_call *) t_alloc (qsysdep->o, T_CALL, T_ADDR);
+ if (qtcall == NULL)
+ {
+ ulog (LOG_ERROR, "t_alloc (T_CALL): %s", ztlierror ());
+ return FALSE;
+ }
+
+ zescape = zbufcpy (zaddr);
+ qtcall->addr.len = cescape (zescape);
+ if (qtcall->addr.len > qtcall->addr.maxlen)
+ {
+ ulog (LOG_ERROR, "%s: TLI address too long (max %d)", zaddr,
+ qtcall->addr.maxlen);
+ ubuffree (zescape);
+ return FALSE;
+ }
+ memcpy (qtcall->addr.buf, zescape, qtcall->addr.len);
+ ubuffree (zescape);
+
+ if (t_connect (qsysdep->o, qtcall, (struct t_call *) NULL) < 0)
+ {
+ if (t_errno != TLOOK)
+ ulog (LOG_ERROR, "t_connect: %s", ztlierror ());
+ else
+ {
+ if (t_rcvdis (qsysdep->o, (struct t_discon *) NULL) < 0)
+ ulog (LOG_ERROR, "t_rcvdis: %s", ztlierror ());
+ else
+ ulog (LOG_ERROR, "Connection refused");
+ }
+ return FALSE;
+ }
+
+ /* We've connected to the remote. Push any desired modules. */
+ if (! ftli_push (qconn))
+ return FALSE;
+
+ /* Handle the rest of the dialer sequence. */
+ if (pzdialer != NULL && *pzdialer != NULL)
+ {
+ if (! fconn_dial_sequence (qconn, puuconf, pzdialer, qsys, zphone,
+ qdialer, ptdialerfound))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#endif /* HAVE_TLI */
diff --git a/gnu/libexec/uucp/libunix/uid.c b/gnu/libexec/uucp/libunix/uid.c
new file mode 100644
index 0000000000000..66b8fc70001fe
--- /dev/null
+++ b/gnu/libexec/uucp/libunix/uid.c
@@ -0,0 +1,116 @@
+/* uid.c
+ Switch back and forth between UUCP and user permissions.
+
+ Copyright (C) 1992, 1995 Ian Lance Taylor
+
+ This file is part of the Taylor UUCP package.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The author of the program may be contacted at ian@airs.com or
+ c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
+ */
+
+#include "uucp.h"
+
+#include "uudefs.h"
+#include "sysdep.h"
+
+#include <errno.h>
+
+/* NetBSD apparently does not support setuid as required by POSIX when
+ using saved setuid, so use seteuid instead. */
+
+#if HAVE_SETEUID
+#define setuid seteuid
+#endif
+
+/* Switch to permissions of the invoking user. */
+
+boolean
+fsuser_perms (pieuid)
+ uid_t *pieuid;
+{
+ uid_t ieuid, iuid;
+
+ ieuid = geteuid ();
+ iuid = getuid ();
+ if (pieuid != NULL)
+ *pieuid = ieuid;
+
+#if HAVE_SETREUID
+ /* Swap the effective user id and the real user id. We can then
+ swap them back again when we want to return to the uucp user's
+ permissions. */
+ if (setreuid (ieuid, iuid) < 0)
+ {
+ ulog (LOG_ERROR, "setreuid (%ld, %ld): %s",
+ (long) ieuid, (long) iuid, strerror (errno));
+ return FALSE;
+ }
+#else /* ! HAVE_SETREUID */
+#if HAVE_SAVED_SETUID
+ /* Set the effective user id to the real user id. Since the
+ effective user id is saved (it's the saved setuid) we will able
+ to set back to it later. If the real user id is root we will not
+ be able to switch back and forth, so don't even try. */
+ if (iuid != 0)
+ {
+ if (setuid (iuid) < 0)
+ {
+ ulog (LOG_ERROR, "setuid (%ld): %s", (long) iuid, strerror (errno));
+ return FALSE;
+ }
+ }
+#else /* ! HAVE_SAVED_SETUID */
+ /* There's no way to switch between real permissions and effective
+ permissions. Just try to open the file with the uucp
+ permissions. */
+#endif /* ! HAVE_SAVED_SETUID */
+#endif /* ! HAVE_SETREUID */
+
+ return TRUE;
+}
+
+/* Restore the uucp permissions. */
+
+/*ARGSUSED*/
+boolean
+fsuucp_perms (ieuid)
+ long ieuid;
+{
+#if HAVE_SETREUID
+ /* Swap effective and real user id's back to what they were. */
+ if (! fsuser_perms ((uid_t *) NULL))
+ return FALSE;
+#else /* ! HAVE_SETREUID */
+#if HAVE_SAVED_SETUID
+ /* Set ourselves back to our original effective user id. */
+ if (setuid ((uid_t) ieuid) < 0)
+ {
+ ulog (LOG_ERROR, "setuid (%ld): %s", (long) ieuid, strerror (errno));
+ /* Is this error message helpful or confusing? */
+ if (errno == EPERM)
+ ulog (LOG_ERROR,
+ "Probably HAVE_SAVED_SETUID in policy.h should be set to 0");
+ return FALSE;
+ }
+#else /* ! HAVE_SAVED_SETUID */
+ /* We didn't switch, no need to switch back. */
+#endif /* ! HAVE_SAVED_SETUID */
+#endif /* ! HAVE_SETREUID */
+
+ return TRUE;
+}
diff --git a/gnu/libexec/uucp/libuuconf/strip.c b/gnu/libexec/uucp/libuuconf/strip.c
new file mode 100644
index 0000000000000..fc314a77e939f
--- /dev/null
+++ b/gnu/libexec/uucp/libuuconf/strip.c
@@ -0,0 +1,50 @@
+/* maxuxq.c
+ Get information about what things should be stripped.
+
+ Copyright (C) 1995 Ian Lance Taylor
+
+ This file is part of the Taylor UUCP uuconf library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License
+ as published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The author of the program may be contacted at ian@airs.com or
+ c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
+ */
+
+#include "uucnfi.h"
+
+#if USE_RCS_ID
+const char _uuconf_strip_rcsid[] = "$Id: strip.c,v 1.2 1995/06/28 15:43:14 ian Rel $";
+#endif
+
+/* Get information about what types of global information should be
+ stripped. There are currently only two, which we return as a
+ couple of bits. We store them as two separate variables, so we
+ don't need to have a special function to set the values correctly. */
+
+int
+uuconf_strip (pglobal, pistrip)
+ pointer pglobal;
+ int *pistrip;
+{
+ struct sglobal *qglobal = (struct sglobal *) pglobal;
+
+ *pistrip = 0;
+ if (qglobal->qprocess->fstrip_login)
+ *pistrip |= UUCONF_STRIP_LOGIN;
+ if (qglobal->qprocess->fstrip_proto)
+ *pistrip |= UUCONF_STRIP_PROTO;
+ return UUCONF_SUCCESS;
+}
diff --git a/gnu/libexec/uucp/uucico/proty.c b/gnu/libexec/uucp/uucico/proty.c
new file mode 100644
index 0000000000000..f15671e2b4d34
--- /dev/null
+++ b/gnu/libexec/uucp/uucico/proty.c
@@ -0,0 +1,660 @@
+/* proty.c
+ The 'y' protocol.
+
+ Copyright (C) 1994, 1995 Jorge Cwik and Ian Lance Taylor
+
+ This file is part of the Taylor UUCP package.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "uucp.h"
+
+#if USE_RCS_ID
+const char proty_id[] = "$Id: proty.c,v 1.4 1995/06/21 19:15:40 ian Rel $";
+#endif
+
+#include "uudefs.h"
+#include "uuconf.h"
+#include "conn.h"
+#include "trans.h"
+#include "system.h"
+#include "prot.h"
+
+/* The 'y' protocol, and this implementation, was written and designed
+ by Jorge Cwik <jorge@satlink.net>. Some of the routines, and the
+ coding style in general, were taken verbatim or adapted from other
+ Taylor UUCP modules. Mark Delany made the initial testings and
+ helped in portability issues.
+
+ This protocol does not perform any kind of error correction or flow
+ control. It does do error checking. It does not require an end to
+ end reliable link. It is recommended for error-free (also called
+ semi-reliable) connections as provided by error correcting modems.
+ It needs an eight bit clean channel and some kind of flow control
+ at the lower layers, typically RTS/CTS hardware flow control.
+
+ The flow of the file transmission is completely unidirectional.
+ There are no ACKs or NAKs outside file boundaries. This makes it
+ very suitable for half duplex modulations (like PEP) and
+ connections with very long delays, like multihop satellite links. */
+
+/* This protocol uses 16 bit little-endian ints in the packet header. */
+#define FROMLITTLE(p) (((p)[0] & 0xff) + (((p)[1] & 0xff) << 8))
+#define TOLITTLE(p, i) ((p)[0] = (i) & 0xff, (p)[1] = ((i) >> 8) & 0xff)
+
+/* The buffer and packet size we use. */
+#define CYBUFSIZE (1024)
+#define IYPACKSIZE (1024)
+
+/* The offset in the buffer to the data. */
+#define CYFRAMELEN (6)
+
+/* Offsets in a packet header. */
+#define YFRAME_SEQ_OFF (0)
+#define YFRAME_LEN_OFF (2)
+#define YFRAME_CTL_OFF (2)
+#define YFRAME_CHK_OFF (4)
+
+/* Offsets in a packet header viewed as an array of shorts. */
+#define YFRAME_SEQ (0)
+#define YFRAME_LEN (1)
+#define YFRAME_CTL (1)
+#define YFRAME_CHK (2)
+
+/* The default timeout. */
+#define CYTIMEOUT (60)
+
+/* Control packet types. */
+#define YPKT_ACK (0xFFFE)
+#define YPKT_ERR (0xFFFD)
+#define YPKT_BAD (0xFFFC)
+
+/* The protocol version number. */
+#define Y_VERSION (1)
+
+/* When the protocol starts up, it transmit the following information:
+ 1 byte version
+ 1 byte packet size
+ 2 byte flags (none currently defined)
+ Future revision may expand the structure as long as these members
+ keep their current offset. */
+#define Y_INIT_HDR_LEN (4)
+#define Y_INIT_HDR_VERSION_OFF (0)
+#define Y_INIT_HDR_PKTSIZE_OFF (1)
+#define Y_INIT_HDR_FLAGS_OFF (2)
+
+/* The initialization length of the lowest accepted version. */
+#define MIN_Y_SYNC (4)
+
+/* Not strictly needed, but I would not want to accept a 32k sync pkt. */
+#define MAX_Y_SYNC IYPACKSIZE
+
+/* Local and remote packet sizes (we actually use the same value for
+ both). */
+static size_t iYlocal_packsize = IYPACKSIZE;
+static size_t iYremote_packsize = IYPACKSIZE;
+
+/* Local and remote packet sequence numbers. */
+static unsigned short iYlocal_pktnum;
+static unsigned short iYremote_pktnum;
+
+/* The timeout. */
+static int cYtimeout = CYTIMEOUT;
+
+/* Transmitter buffer. */
+static char *zYbuf;
+
+/* Protocol parameters. */
+
+struct uuconf_cmdtab asYproto_params[] =
+{
+ { "timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cYtimeout, NULL },
+ { "packet-size", UUCONF_CMDTABTYPE_INT, (pointer) &iYlocal_packsize, NULL },
+ { NULL, 0, NULL, NULL }
+};
+
+/* Local functions. */
+
+static boolean fywait_for_packet P((struct sdaemon *qdaemon,
+ boolean *pfexit));
+static unsigned short iychecksum P((const char *z, size_t c));
+static unsigned short iychecksum2 P((const char *zfirst, size_t cfirst,
+ const char *zsecond, size_t csecond));
+static boolean fywait_for_header P((struct sdaemon *qdaemon,
+ unsigned short header[3], int timeout));
+static boolean fysend_pkt P((struct sdaemon *qdaemon,
+ const void *zdata, size_t cdata));
+static boolean fysend_control P((struct sdaemon *qdaemon,
+ int itype));
+static boolean fyread_data P((struct sdaemon *qdaemon, size_t clen,
+ int timeout));
+
+/* Exchange sync packets at protocol startup. */
+
+static boolean
+fyxchg_syncs (qdaemon)
+ struct sdaemon *qdaemon;
+{
+ char inithdr[Y_INIT_HDR_LEN];
+ unsigned short header[3];
+ unsigned short ichk;
+ size_t clen, cfirst;
+ int rpktsize;
+
+ /* Send our configuration. We could use only one array (for local
+ and remote). But this is safer in case the code changes and
+ depend on separate ones. */
+
+ inithdr[Y_INIT_HDR_VERSION_OFF] = Y_VERSION;
+ inithdr[Y_INIT_HDR_PKTSIZE_OFF] = iYlocal_packsize >> 8;
+ TOLITTLE (inithdr + Y_INIT_HDR_FLAGS_OFF, 0);
+
+ if (! fysend_pkt (qdaemon, inithdr, Y_INIT_HDR_LEN))
+ return FALSE;
+
+ if (! fywait_for_header (qdaemon, header, cYtimeout))
+ return FALSE;
+
+ DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO, "fyxchg_syncs: Got sync header");
+ clen = header[YFRAME_LEN];
+
+ if (clen < MIN_Y_SYNC || clen > MAX_Y_SYNC)
+ {
+ ulog (LOG_ERROR, "Bad 'y' protocol sync packet length");
+ return FALSE;
+ }
+
+ /* It may be better to integrate this code with fywait_for_packet. */
+ if (! fyread_data (qdaemon, clen, cYtimeout))
+ return FALSE;
+
+ cfirst = CRECBUFLEN - iPrecstart;
+ ichk = iychecksum2 (abPrecbuf + iPrecstart, cfirst,
+ abPrecbuf, clen - cfirst);
+
+ rpktsize = BUCHAR (abPrecbuf[(iPrecstart + 1) % CRECBUFLEN]);
+
+ /* Future versions of the protocol may need to check and react
+ according to the version number. */
+
+ if (rpktsize == 0 || header[YFRAME_CHK] != ichk)
+ {
+ ulog (LOG_ERROR, "Bad 'y' protocol sync packet");
+ return FALSE;
+ }
+
+ iYremote_packsize = rpktsize << 8;
+
+ /* Some may want to do this different and in effect the protocol
+ support this. But I like the idea that the packet size would be
+ the same in both directions. This allows the caller to select
+ both packet sizes without changing the configuration at the
+ server. */
+ if (iYremote_packsize > iYlocal_packsize)
+ iYremote_packsize = iYlocal_packsize;
+
+ iPrecstart = (iPrecstart + clen) % CRECBUFLEN;
+ return TRUE;
+}
+
+/* Start the protocol. */
+
+boolean
+fystart (qdaemon, pzlog)
+ struct sdaemon *qdaemon;
+ char **pzlog;
+{
+ *pzlog = NULL;
+
+ /* This should force, or at least enable if available, RTS/CTS
+ hardware flow control !! */
+
+ /* The 'y' protocol requires an eight bit clean link */
+ if (! fconn_set (qdaemon->qconn, PARITYSETTING_NONE,
+ STRIPSETTING_EIGHTBITS, XONXOFF_OFF))
+ return FALSE;
+
+ iYlocal_pktnum = iYremote_pktnum = 0;
+
+ /* Only multiple of 256 sizes are allowed */
+ iYlocal_packsize &= ~0xff;
+ if (iYlocal_packsize < 256 || iYlocal_packsize > (16*1024))
+ iYlocal_packsize = IYPACKSIZE;
+
+ /* Exhange SYNC packets */
+ if (! fyxchg_syncs (qdaemon))
+ {
+ /* Restore defaults */
+ cYtimeout = CYTIMEOUT;
+ iYlocal_packsize = IYPACKSIZE;
+ return FALSE;
+ }
+
+ zYbuf = (char *) xmalloc (CYBUFSIZE + CYFRAMELEN);
+ return TRUE;
+}
+
+/* Shutdown the protocol. */
+
+boolean
+fyshutdown (qdaemon)
+ struct sdaemon *qdaemon;
+{
+ xfree ((pointer) zYbuf);
+ zYbuf = NULL;
+ cYtimeout = CYTIMEOUT;
+ iYlocal_packsize = IYPACKSIZE;
+ return TRUE;
+}
+
+/* Send a command string. We send packets containing the string until
+ the entire string has been sent, including the zero terminator. */
+
+/*ARGSUSED*/
+boolean
+fysendcmd (qdaemon, z, ilocal, iremote)
+ struct sdaemon *qdaemon;
+ const char *z;
+ int ilocal;
+ int iremote;
+{
+ size_t clen;
+
+ DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO, "fysendcmd: Sending command \"%s\"", z);
+
+ clen = strlen (z) + 1;
+
+ while (clen > 0)
+ {
+ size_t csize;
+
+ csize = clen;
+ if (csize > iYremote_packsize)
+ csize = iYremote_packsize;
+
+ if (! fysend_pkt (qdaemon, z, csize))
+ return FALSE;
+
+ z += csize;
+ clen -= csize;
+ }
+
+ return TRUE;
+}
+
+/* Get space to be filled with data. We always use zYbuf, which was
+ allocated from the heap. */
+
+char *
+zygetspace (qdaemon, pclen)
+ struct sdaemon *qdaemon;
+ size_t *pclen;
+{
+ *pclen = iYremote_packsize;
+ return zYbuf + CYFRAMELEN;
+}
+
+/* Send out a data packet. */
+
+boolean
+fysenddata (qdaemon, zdata, cdata, ilocal, iremote, ipos)
+ struct sdaemon *qdaemon;
+ char *zdata;
+ size_t cdata;
+ int ilocal;
+ int iremote;
+ long ipos;
+{
+#if DEBUG > 0
+ if (cdata > iYremote_packsize)
+ ulog (LOG_FATAL, "fysend_packet: Packet size too large");
+#endif
+
+ TOLITTLE (zYbuf + YFRAME_SEQ_OFF, iYlocal_pktnum);
+ ++iYlocal_pktnum;
+ TOLITTLE (zYbuf + YFRAME_LEN_OFF, cdata);
+ TOLITTLE (zYbuf + YFRAME_CHK_OFF, iychecksum (zdata, cdata));
+
+ /* We pass FALSE to fsend_data since we don't expect the other side
+ to be sending us anything just now. */
+ return fsend_data (qdaemon->qconn, zYbuf, cdata + CYFRAMELEN, FALSE);
+}
+
+/* Wait for data to come in and process it until we've finished a
+ command or a file. */
+
+boolean
+fywait (qdaemon)
+ struct sdaemon *qdaemon;
+{
+ boolean fexit = FALSE;
+
+ while (! fexit)
+ {
+ if (! fywait_for_packet (qdaemon, &fexit))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* File level routines
+ We could handle this inside the other public routines,
+ but this is cleaner and better for future expansions */
+
+boolean
+fyfile (qdaemon, qtrans, fstart, fsend, cbytes, pfhandled)
+ struct sdaemon *qdaemon;
+ struct stransfer *qtrans;
+ boolean fstart;
+ boolean fsend;
+ long cbytes;
+ boolean *pfhandled;
+{
+ unsigned short header[3];
+
+ *pfhandled = FALSE;
+
+ if (! fstart)
+ {
+ if (fsend)
+ {
+ /* It is critical that the timeout here would be long
+ enough. We have just sent a full file without any kind
+ of flow control at the protocol level. The traffic may
+ be buffered in many places of the link, and the remote
+ may take a while until cathing up. */
+ if (! fywait_for_header (qdaemon, header, cYtimeout * 2))
+ return FALSE;
+
+ if (header[YFRAME_CTL] != (unsigned short) YPKT_ACK)
+ {
+ DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL,
+ "fyfile: Error from remote: 0x%04X", header[1]);
+ ulog (LOG_ERROR, "Received 'y' protocol error from remote");
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* This is technically not requireed. But I've put this in
+ the protocol to allow easier expansions. */
+ return fysend_control (qdaemon, YPKT_ACK);
+ }
+ }
+
+ return TRUE;
+}
+
+/* Send a control packet, not used during the normal file
+ transmission. */
+
+static boolean
+fysend_control (qdaemon, itype)
+ struct sdaemon *qdaemon;
+ int itype;
+{
+ char header[CYFRAMELEN];
+
+ TOLITTLE (header + YFRAME_SEQ_OFF, iYlocal_pktnum);
+ iYlocal_pktnum++;
+ TOLITTLE (header + YFRAME_CTL_OFF, itype);
+ TOLITTLE (header + YFRAME_CHK_OFF, 0);
+
+ return fsend_data (qdaemon->qconn, header, CYFRAMELEN, FALSE);
+}
+
+/* Private function to send a packet. This one doesn't need the data
+ to be in the buffer provided by zygetspace. I've found it worth
+ for avoiding memory copies. Somebody may want to do it otherwise */
+
+static boolean
+fysend_pkt (qdaemon, zdata, cdata)
+ struct sdaemon *qdaemon;
+ const void *zdata;
+ size_t cdata;
+{
+ char header[CYFRAMELEN];
+
+ TOLITTLE (header + YFRAME_SEQ_OFF, iYlocal_pktnum);
+ iYlocal_pktnum++;
+ TOLITTLE (header + YFRAME_LEN_OFF, cdata);
+ TOLITTLE (header + YFRAME_CHK_OFF, iychecksum (zdata, cdata));
+
+ if (! fsend_data (qdaemon->qconn, header, CYFRAMELEN, FALSE))
+ return FALSE;
+ return fsend_data (qdaemon->qconn, zdata, cdata, FALSE);
+}
+
+/* Wait until enough data arrived from the comm line. This protocol
+ doesn't need to perform any kind of action while waiting. */
+
+static boolean
+fyread_data (qdaemon, clen, timeout)
+ struct sdaemon *qdaemon;
+ size_t clen;
+ int timeout;
+{
+ int cinbuf;
+ size_t crec;
+
+ cinbuf = iPrecend - iPrecstart;
+ if (cinbuf < 0)
+ cinbuf += CRECBUFLEN;
+
+ if (cinbuf < clen)
+ {
+ if (! freceive_data (qdaemon->qconn, clen - cinbuf, &crec,
+ timeout, TRUE))
+ return FALSE;
+ cinbuf += crec;
+ if (cinbuf < clen)
+ {
+ if (! freceive_data (qdaemon->qconn, clen - cinbuf, &crec,
+ timeout, TRUE))
+ return FALSE;
+ }
+ cinbuf += crec;
+ if (cinbuf < clen)
+ {
+ ulog (LOG_ERROR, "Timed out waiting for data");
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* Receive a remote packet header, check for correct sequence number. */
+
+static boolean
+fywait_for_header (qdaemon, header, timeout)
+ struct sdaemon *qdaemon;
+ unsigned short header[3];
+ int timeout;
+{
+ if (! fyread_data (qdaemon, CYFRAMELEN, timeout))
+ return FALSE;
+
+ /* Somebody may want to optimize this in a portable way. I'm not
+ sure it's worth, but the output by gcc for the portable construct
+ is so bad (even with optimization), that I couldn't resist. */
+
+ if (iPrecstart <= (CRECBUFLEN - CYFRAMELEN))
+ {
+ header[0] = FROMLITTLE (abPrecbuf + iPrecstart);
+ header[1] = FROMLITTLE (abPrecbuf + iPrecstart + 2);
+ header[2] = FROMLITTLE (abPrecbuf + iPrecstart + 4);
+ }
+ else
+ {
+ register int i, j;
+
+ for (i = j = 0; j < CYFRAMELEN; i++, j += 2)
+ {
+ header[i] =
+ (((abPrecbuf[(iPrecstart + j + 1) % CRECBUFLEN] & 0xff) << 8)
+ + (abPrecbuf[(iPrecstart + j) % CRECBUFLEN] & 0xff));
+ }
+ }
+
+ iPrecstart = (iPrecstart + CYFRAMELEN) % CRECBUFLEN;
+
+ DEBUG_MESSAGE3 (DEBUG_UUCP_PROTO,
+ "fywait_for_header: Got header: 0x%04X, 0x%04X, 0x%04X",
+ header[0], header[1], header[2]);
+
+ if (header[YFRAME_SEQ] != iYremote_pktnum++)
+ {
+ ulog (LOG_ERROR, "Incorrect 'y' packet sequence");
+ fysend_control (qdaemon, YPKT_BAD);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Receive a remote data packet */
+
+static boolean
+fywait_for_packet (qdaemon, pfexit)
+ struct sdaemon *qdaemon;
+ boolean *pfexit;
+{
+ unsigned short header[3], ichk;
+ size_t clen, cfirst;
+
+ if (! fywait_for_header (qdaemon, header, cYtimeout))
+ return FALSE;
+
+ clen = header[YFRAME_LEN];
+ if (clen == 0 && pfexit != NULL)
+ {
+ /* I Suppose the pointers could be NULL ??? */
+ return fgot_data (qdaemon, abPrecbuf, 0, abPrecbuf, 0,
+ -1, -1, (long) -1, TRUE, pfexit);
+ }
+
+ if (clen & 0x8000)
+ {
+ DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL,
+ "fywait_for_packet: Error from remote: 0x%04X",
+ header[YFRAME_CTL]);
+ ulog (LOG_ERROR, "Remote error packet");
+ return FALSE;
+ }
+
+ /* This is really not neccessary. But if this check is removed,
+ take in mind that the packet may be up to 32k long. */
+ if (clen > iYlocal_packsize)
+ {
+ ulog (LOG_ERROR, "Packet too large");
+ return FALSE;
+ }
+
+ if (! fyread_data (qdaemon, clen, cYtimeout))
+ return FALSE;
+
+ cfirst = CRECBUFLEN - iPrecstart;
+ if (cfirst > clen)
+ cfirst = clen;
+
+ if (cfirst == clen)
+ ichk = iychecksum (abPrecbuf + iPrecstart, clen);
+ else
+ ichk = iychecksum2 (abPrecbuf + iPrecstart, cfirst,
+ abPrecbuf, clen - cfirst);
+ if (header[YFRAME_CHK] != ichk)
+ {
+ DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL,
+ "fywait_for_packet: Bad checksum 0x%x != 0x%x",
+ header[YFRAME_CHK], ichk);
+ fysend_control (qdaemon, YPKT_ERR);
+ ulog (LOG_ERROR, "Checksum error");
+ return FALSE;
+ }
+
+ if (pfexit != NULL
+ && ! fgot_data (qdaemon, abPrecbuf + iPrecstart, cfirst,
+ abPrecbuf, clen - cfirst,
+ -1, -1, (long) -1, TRUE, pfexit))
+ return FALSE;
+
+ iPrecstart = (iPrecstart + clen) % CRECBUFLEN;
+
+ return TRUE;
+}
+
+/* Compute 16 bit checksum */
+
+#ifdef __GNUC__
+#ifdef __i386__
+#define I386_ASM
+#endif
+#endif
+
+#ifdef I386_ASM
+#define ROTATE(i) \
+ asm ("rolw $1,%0" : "=g" (i) : "g" (i))
+#else
+#define ROTATE(i) i += i + ((i & 0x8000) >> 15)
+#endif
+
+static unsigned short
+iychecksum (z, c)
+ register const char *z;
+ register size_t c;
+{
+ register unsigned short ichk;
+
+ ichk = 0xffff;
+
+ while (c-- > 0)
+ {
+ ROTATE (ichk);
+ ichk += BUCHAR (*z++);
+ }
+
+ return ichk;
+}
+
+static unsigned short
+iychecksum2 (zfirst, cfirst, zsecond, csecond)
+ const char *zfirst;
+ size_t cfirst;
+ const char *zsecond;
+ size_t csecond;
+{
+ register unsigned short ichk;
+ register const char *z;
+ register size_t c;
+
+ z = zfirst;
+ c = cfirst + csecond;
+
+ ichk = 0xffff;
+
+ while (c-- > 0)
+ {
+ ROTATE (ichk);
+ ichk += BUCHAR (*z++);
+
+ /* If the first buffer has been finished, switch to the second. */
+ if (--cfirst == 0)
+ z = zsecond;
+ }
+
+ return ichk;
+}
diff --git a/gnu/usr.bin/ld/rtld/rtld.1 b/gnu/usr.bin/ld/rtld/rtld.1
new file mode 100644
index 0000000000000..9179f25793a11
--- /dev/null
+++ b/gnu/usr.bin/ld/rtld/rtld.1
@@ -0,0 +1,144 @@
+.\" $NetBSD: rtld.1,v 1.1 1995/06/30 12:23:10 pk Exp $
+.\"
+.\" Copyright (c) 1995 Paul Kranenburg
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Paul Kranenburg.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd June 27, 1995
+.Dt RTLD 1
+.Os NetBSD
+.Sh NAME
+.Nm ld.so
+.Nd run-time link-editor
+.Sh DESCRIPTION
+.Nm
+is a self-contained, position independent program image providing run-time
+support for loading and link-editing shared objects into a process'
+address space. It uses the data structures
+.Po
+see
+.Xr link 5
+.Pc
+contained within dynamically linked programs to determine which shared
+libraries are needed and loads them at a convenient virtual address
+using the
+.Xr mmap 2
+system call.
+.Pp
+After all shared libraries have been succesfully loaded,
+.Nm
+proceeds to resolve external references from both the main program and
+all objects loaded. A mechanism is provided for initialisation routines
+to be called, on a per-object basis, giving a shared object an opportunity
+to perfrom any extra set-up, before execution of the program proper begins.
+This is useful for C++ libraries that contain static constrictors.
+.Pp
+.Nm
+is itself a shared object that is initially loaded by the startup module
+.Em crt0 .
+Since
+.Xr a.out 5
+formats do not provide easy access to the file header from within a running
+process,
+.Em crt0
+uses the special symbol
+.Va _DYNAMIC
+to determine whether a program is in fact dynamically linked or not. Whenever
+the linker
+.Xr ld 1
+has relocated this symbol to a location other then 0,
+.Em crt0
+assumes the services of
+.Nm
+are needed
+.Po
+see
+.Xr link 5
+for details
+.Pc \&.
+.Em crt0
+passes control to
+.Nm
+\&'s entry point before the program's
+.Fn main
+routine is called. Thus,
+.Nm
+can complete the link-editing process before the dynamic program calls upon
+services of any dynamic library.
+.Pp
+To quickly locate the required shared objects in the filesystem,
+.Nm
+may use a
+.Dq hints
+file, prepared by the
+.Xr ldconfig 8
+utility, in which the full path specification of the shared objects can be
+looked up by hashing on the 3-tuple
+.Ao
+library-name, major-version-number, minor-version-number
+.Ac \&.
+.Pp
+.Nm
+recognises a number of environment variables that can be used to modify
+its behaviour as follows:
+.Pp
+.Bl -tag -width "LD_TRACE_LOADED_OBJECTS"
+.It Ev LD_LIBRARY_PATH
+A colon separated list of directories, overriding the default search path
+for shared libraries.
+.It Ev LD_WARN_NON_PURE_CODE
+When set, issue a warning whenever a link-editing operation requires
+modification of the text segment of some loaded object. This is usually
+indicative of an incorrectly built library.
+.It Ev LD_SUPPRESS_WARNINGS
+When set, no warning messages of any kind are issued. Normally, a warning
+is given if satisfactorily versioned library could not be found.
+.It Ev LD_TRACE_LOADED_OBJECTS
+When set, causes
+.Nm
+to exit after loading the shared objects and printing a summary which includes
+the absolute pathnames of all objects, to standard output.
+.It Ev LD_NO_INTERN_SEARCH
+When set,
+.Nm
+does not process any internal search paths that were recorded in the
+executable.
+.It Ev LD_NOSTD_PATH
+When set, do not include a set of built-in standard directory paths for
+searching. This might be useful when running on a system with a completely
+non-standard filesystem layout.
+.El
+.Pp
+.Sh FILES
+/var/run/ld.so.hints
+.Pp
+.Sh SEE ALSO
+.Xr ld 1
+.Xr ldconfig 8
+.Xr link 5
+.Sh HISTORY
+The shared library model employed first appeared in SunOS 4.0
diff --git a/gnu/usr.sbin/ypserv/svc_run.c b/gnu/usr.sbin/ypserv/svc_run.c
new file mode 100644
index 0000000000000..6f4a52c0b8a64
--- /dev/null
+++ b/gnu/usr.sbin/ypserv/svc_run.c
@@ -0,0 +1,85 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: svc_run.c,v 1.2 1995/05/30 05:41:35 rgrimes Exp $";
+#endif
+
+/*
+ * This is the rpc server side idle loop
+ * Wait for input, call server program.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include <sys/errno.h>
+
+extern int _rpc_dtablesize __P((void));
+
+void
+my_svc_run()
+{
+#ifdef FD_SETSIZE
+ fd_set readfds;
+#else
+ int readfds;
+#endif /* def FD_SETSIZE */
+ extern int errno;
+ extern int forked;
+ int pid;
+
+ /* Establish the identity of the parent ypserv process. */
+ pid = getpid();
+
+ for (;;) {
+#ifdef FD_SETSIZE
+ readfds = svc_fdset;
+#else
+ readfds = svc_fds;
+#endif /* def FD_SETSIZE */
+ switch (select(_rpc_dtablesize(), &readfds, NULL, NULL,
+ (struct timeval *)0)) {
+ case -1:
+ if (errno == EINTR) {
+ continue;
+ }
+ perror("svc_run: - select failed");
+ return;
+ case 0:
+ continue;
+ default:
+ svc_getreqset(&readfds);
+ if (forked && pid != getpid())
+ exit(0);
+ }
+ }
+}
diff --git a/lib/libc/net/res_config.h b/lib/libc/net/res_config.h
new file mode 100644
index 0000000000000..a1339d9652a14
--- /dev/null
+++ b/lib/libc/net/res_config.h
@@ -0,0 +1,7 @@
+#define DEBUG 1 /* enable debugging code (needed for dig) */
+#undef ALLOW_T_UNSPEC /* enable the "unspec" RR type for old athena */
+#define RESOLVSORT /* allow sorting of addresses in gethostbyname */
+#undef RFC1535 /* comply with RFC1535 */
+#undef ALLOW_UPDATES /* destroy your system security */
+#undef USELOOPBACK /* res_init() bind to localhost */
+#undef SUNSECURITY /* verify gethostbyaddr() calls - WE DONT NEED IT */
diff --git a/lib/libtermcap/tospeed.c b/lib/libtermcap/tospeed.c
new file mode 100644
index 0000000000000..dd2026ad3ecbc
--- /dev/null
+++ b/lib/libtermcap/tospeed.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 1995 by Andrey A. Chernov, Moscow, Russia.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <termios.h>
+#include "termcap.h"
+
+static struct stable {
+ speed_t speed;
+ short code;
+} table[] = {
+ {B115200,17},
+ {B57600, 16},
+ {B38400, 15},
+ {B19200, 14},
+ {B9600, 13},
+ {B4800, 12},
+ {B2400, 11},
+ {B1800, 10},
+ {B1200, 9},
+ {B600, 8},
+ {B300, 7},
+ {B200, 6},
+ {B150, 5},
+ {B134, 4},
+ {B110, 3},
+ {B75, 2},
+ {B50, 1},
+ {B0, 0},
+ {-1, -1}
+};
+
+void __set_ospeed(speed_t speed)
+{
+ struct stable *stable;
+
+ if (speed == B0) {
+ ospeed = 0;
+ return;
+ }
+ for (stable = table; stable->speed > B0; stable++) {
+ /* nearest one, rounded down */
+ if (stable->speed <= speed) {
+ ospeed = stable->code;
+ return;
+ }
+ }
+ ospeed = 1; /* 50, min and not hangup */
+}
+
diff --git a/lkm/linux/Makefile b/lkm/linux/Makefile
new file mode 100644
index 0000000000000..11650c59e8334
--- /dev/null
+++ b/lkm/linux/Makefile
@@ -0,0 +1,16 @@
+# $Id$
+
+.PATH: ${.CURDIR}/../../sys/i386/linux
+KMOD= linux_mod
+SRCS= linux.c linux_file.c linux_ioctl.c linux_misc.c linux_signal.c \
+ linux_generic.c linux_ipc.c linux_socket.c linux_stats.c \
+ linux_dummy.c linux_sysent.c imgact_linux.c vnode_if.h
+NOMAN=
+CFLAGS+= -DLKM -I. -DCOMPAT_LINUX -DSYSVSHM #-DSYSVMSG -DSYSVSEM #-DDEBUG
+CLEANFILES+= vnode_if.h vnode_if.c
+
+afterinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${.CURDIR}/linux /usr/bin
+
+.include <bsd.kmod.mk>
diff --git a/lkm/linux/linux b/lkm/linux/linux
new file mode 100644
index 0000000000000..e4c36068cfa31
--- /dev/null
+++ b/lkm/linux/linux
@@ -0,0 +1,3 @@
+#!/bin/sh
+# $Id$
+modload -e linux_init /lkm/linux_mod.o
diff --git a/lkm/linux/linux.c b/lkm/linux/linux.c
new file mode 100644
index 0000000000000..183ad3e492549
--- /dev/null
+++ b/lkm/linux/linux.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 1994 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux.c,v 1.1 1994/10/14 08:46:12 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/conf.h>
+#include <sys/sysent.h>
+#include <sys/lkm.h>
+#include <sys/errno.h>
+
+extern const struct execsw linux_execsw;
+
+MOD_EXEC("linux_emulator", -1, (struct execsw*)&linux_execsw)
+
+linux_load(struct lkm_table *lkmtp, int cmd)
+{
+ uprintf("Linux emulator installed\n");
+ return 0;
+}
+
+linux_unload(struct lkm_table *lkmtp, int cmd)
+{
+ uprintf("Linux emulator removed\n");
+ return 0;
+}
+
+linux_init(struct lkm_table *lkmtp, int cmd, int ver)
+{
+ DISPATCH(lkmtp, cmd, ver, linux_load, linux_unload, nosys);
+}
diff --git a/secure/libexec/Makefile b/secure/libexec/Makefile
new file mode 100644
index 0000000000000..9bd4d2e61f2c1
--- /dev/null
+++ b/secure/libexec/Makefile
@@ -0,0 +1,6 @@
+# From: @(#)Makefile 8.1 (Berkeley) 5/31/93
+# $Id: Makefile,v 1.2 1995/07/25 14:03:35 mark Exp $
+
+SUBDIR= telnetd
+
+.include <bsd.subdir.mk>
diff --git a/secure/libexec/Makefile.inc b/secure/libexec/Makefile.inc
new file mode 100644
index 0000000000000..6657676abc6f9
--- /dev/null
+++ b/secure/libexec/Makefile.inc
@@ -0,0 +1,4 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $Id: Makefile,v 1.2 1995/07/25 14:03:35 mark Exp $
+
+BINDIR?= /usr/libexec
diff --git a/share/doc/handbook/install.sgml b/share/doc/handbook/install.sgml
new file mode 100644
index 0000000000000..a22d9a2b6fc77
--- /dev/null
+++ b/share/doc/handbook/install.sgml
@@ -0,0 +1,652 @@
+<!-- $Id: install.sgml,v 1.8 1995/08/26 03:09:12 jfieber Exp $ -->
+<!-- The FreeBSD Documentation Project -->
+
+<!--
+<!DOCTYPE linuxdoc PUBLIC '-//FreeBSD//DTD linuxdoc//EN'>
+-->
+<chapt><heading>Installing FreeBSD<label id="install"></heading>
+
+ <sect><heading>MS-DOS user's Questions and Answers</heading>
+
+ <p><bf>Help! I have no space! Do I need to delete
+ everything first?</bf>
+
+ If your machine is already running MS-DOS and has little
+ or no free space available for FreeBSD's installation,
+ all is not lost! You may find the FIPS utility, provided
+ in the <tt>tools</tt> directory on the FreeBSD CDROM or
+ on the various FreeBSD ftp sites, to be quite useful.
+
+ FIPS allows you to split an existing MS-DOS partition
+ into two pieces, preserving the original partition and
+ allowing you to install onto the second free piece. You
+ first defragment your MS-DOS partition, using the DOS
+ 6.xx DEFRAG utility or the Norton Disk tools, then run
+ FIPS. It will prompt you for the rest of the information
+ it needs. Afterwards, you can reboot and install FreeBSD
+ on the new free slice. See the <em>Distributions</em>
+ menu for an estimation of how much free space you'll need
+ for the kind of installation you want.
+
+
+ <bf>Can I use compressed MS-DOS filesystems from
+ FreeBSD?</bf>
+
+ No. If you are using a utility such as Stacker(tm) or
+ DoubleSpace(tm), FreeBSD will only be able to use
+ whatever portion of the filesystem you leave
+ uncompressed. The rest of the filesystem will show up as
+ one large file (the stacked/dblspaced file!). <bf>Do not
+ remove that file!</bf> You will probably regret it
+ greatly!
+
+ It is probably better to create another uncompressed
+ MS-DOS primary partition and use this for communications
+ between MS-DOS and FreeBSD.
+
+
+ <bf>Can I mount my MS-DOS extended partitions?</bf>
+
+ This feature isn't in FreeBSD 2.0.5 but should be in 2.1.
+ We've laid all the groundwork for making this happen, now
+ we just need to do the last 1 percent of the work involved.
+
+
+ <bf>Can I run MS-DOS binaries under FreeBSD?</bf>
+
+ Not yet! We'd like to add support for this someday, but
+ are still lacking anyone to actually do the work.
+ Ongoing work with Linux's PCEMU utility may bring this
+ much closer to being a reality sometime soon. Send mail
+ to hackers@freebsd.org if you're interested in joining
+ this effort!
+
+
+
+ <sect><heading>Supported Configurations<label id="install:hw"></heading>
+
+ <p>FreeBSD currently runs on a wide variety of ISA, VLB,
+ EISA and PCI bus based PC's, ranging from 386sx to
+ Pentium class machines (though the 386sx is not
+ recommended). Support for generic IDE or ESDI drive
+ configurations, various SCSI controller, network and
+ serial cards is also provided.
+
+ A minimum of four megabytes of RAM is required to run FreeBSD.
+ To run the X-window system, eight megabytes of RAM is the
+ recommended minimum.
+
+ Following is a list of all disk controllers and ethernet
+ cards currently known to work with FreeBSD. Other
+ configurations may very well work, and we have simply not
+ received any indication of this.
+
+ <sect1><heading>Disk Controllers</heading>
+
+ <p>
+ <itemize>
+ <item>WD1003 (any generic MFM/RLL)
+ <item>WD1007 (any generic IDE/ESDI)
+ <item>WD7000
+ <item>IDE
+ <item>ATA
+
+ <item>Adaptec 152x series ISA SCSI controllers
+ <item>Adaptec 154x series ISA SCSI controllers
+ <item>Adaptec 174x series EISA SCSI controller in
+ standard and enhanced mode.
+ <item>Adaptec 274X/284X/2940 <!-- 3940 (in 2.1) -->
+ (Narrow/Wide/Twin)
+ series EISA/VLB/PCI SCSI controllers
+ <item>Adaptec AIC-6260 and AIC-6360 based boards,
+ which includes the AHA-152x and SoundBlaster SCSI
+ cards.
+
+ <bf>Note:</bf> You cannot boot from the
+ SoundBlaster cards as they have no on-board BIOS,
+ which is necessary for mapping the boot device into
+ the system BIOS I/O vectors. They are perfectly
+ usable for external tapes, CDROMs, etc, however.
+ The same goes for any other AIC-6x60 based card
+ without a boot ROM. Some systems DO have a boot
+ ROM, which is generally indicated by some sort of
+ message when the system is first powered up or
+ reset. Check your system/board documentation for
+ more details.
+
+ <item>Buslogic 545S &amp; 545c
+ <bf>Note:</bf> that Buslogic was formerly known as "Bustec".
+ <item>Buslogic 445S/445c VLB SCSI controller
+ <item>Buslogic 742A, 747S, 747c EISA SCSI controller.
+ <item>Buslogic 946c PCI SCSI controller
+ <item>Buslogic 956c PCI SCSI controller
+
+ <item>NCR 53C810 and 53C825 PCI SCSI controller.
+ <item>NCR5380/NCR53400 ("ProAudio Spectrum") SCSI controller.
+
+ <item>DTC 3290 EISA SCSI controller in 1542 emulation mode.
+
+ <item>UltraStor 14F, 24F and 34F SCSI controllers.
+
+ <item>Seagate ST01/02 SCSI controllers.
+
+ <item>Future Domain 8xx/950 series SCSI controllers.
+ </itemize>
+
+ With all supported SCSI controllers, full support is
+ provided for SCSI-I &amp; SCSI-II peripherals,
+ including Disks, tape drives (including DAT) and CD ROM
+ drives.
+
+ The following CD-ROM type systems are supported at this
+ time:
+
+ <itemize>
+ <item>SCSI (also includes ProAudio Spectrum and
+ SoundBlaster SCSI) (cd)
+ <item>Mitsumi proprietary interface (mcd)
+ <item>Matsushita/Panasonic (Creative) proprietary
+ interface (matcd)
+ <item>Sony proprietary interface (scd)
+ </itemize>
+
+ <bf>Note:</bf> CD-Drives with IDE interfaces are not
+ supported at this time.
+
+ Some controllers have limitations with the way they
+ deal with &gt;16MB of memory, due to the fact that the
+ ISA bus only has a DMA address space of 24 bits. If
+ you do your arithmetic, you'll see that this makes it
+ impossible to do direct DMA to any address &gt;16MB.
+ This limitation is even true of some EISA controllers
+ (which are normally 32 bit) when they're configured to
+ emulate an ISA card, which they then do in *all*
+ respects. This problem is avoided entirely by IDE
+ controllers (which do not use DMA), true EISA
+ controllers (like the UltraStor, Adaptec 1742A or
+ Adaptec 2742) and most VLB (local bus) controllers. In
+ the cases where it's necessary, the system will use
+ "bounce buffers" to talk to the controller so that you
+ can still use more than 16Mb of memory without
+ difficulty.
+
+
+ <sect1><heading>Ethernet cards</heading>
+
+ <p>
+ <itemize>
+
+ <item>SMC Elite 16 WD8013 ethernet interface, and
+ most other WD8003E, WD8003EBT, WD8003W, WD8013W,
+ WD8003S, WD8003SBT and WD8013EBT based clones. SMC
+ Elite Ultra is also supported.
+
+ <item>DEC EtherWORKS III NICs (DE203, DE204, and DE205)
+ <item>DEC EtherWORKS II NICs (DE200, DE201, DE202, and DE422)
+ <item>DEC DC21140 based NICs (SMC???? DE???)
+ <item>DEC FDDI (DEFPA/DEFEA) NICs
+
+ <item>Fujitsu MB86960A family of NICs
+
+ <item>Intel EtherExpress
+
+ <item>Isolan AT 4141-0 (16 bit)
+ <item>Isolink 4110 (8 bit)
+
+ <item>Novell NE1000, NE2000, and NE2100 ethernet interface.
+
+ <item>3Com 3C501 cards
+
+ <item>3Com 3C503 Etherlink II
+
+ <item>3Com 3c505 Etherlink/+
+
+ <item>3Com 3C507 Etherlink 16/TP
+
+ <item>3Com 3C509, 3C579, 3C589 (PCMCIA) Etherlink III
+
+ <item>Toshiba ethernet cards
+
+ <item>PCMCIA ethernet cards from IBM and National
+ Semiconductor are also supported.
+ </itemize>
+
+ <sect1><heading>Miscellaneous devices</heading>
+
+ <p>
+ <itemize>
+ <item>AST 4 port serial card using shared IRQ.
+
+ <item>ARNET 8 port serial card using shared IRQ.
+
+ <item>BOCA ATIO66 6 port serial card using shared IRQ.
+
+ <item>Cyclades Cyclom-y Serial Board.
+
+ <item>STB 4 port card using shared IRQ.
+
+ <item>Mitsumi (all models) CDROM interface and drive.
+
+ <item>SDL Communications Riscom/8 Serial Board.
+
+ <item>Soundblaster SCSI and ProAudio Spectrum SCSI
+ CDROM interface and drive.
+
+ <item>Matsushita/Panasonic (Creative SoundBlaster)
+ CDROM interface and drive.
+
+ <item>Adlib, SoundBlaster, SoundBlaster Pro,
+ ProAudioSpectrum, Gravis UltraSound and Roland
+ MPU-401 sound cards.
+
+ </itemize>
+
+ FreeBSD currently does NOT support IBM's microchannel
+ (MCA) bus, but support is apparently close to
+ materializing. Details will be posted as the situation
+ develops.
+
+ <sect><heading>Preparing for the installation</heading>
+
+ <p>There are a number of different methods by which FreeBSD
+ can be installed. The following describes what
+ preparation needs to be done for each type.
+
+ <sect1><heading>Before installing from CDROM</heading>
+
+ <p>If your CDROM is of an unsupported type, such as an
+ IDE CDROM, then please skip to section 2.3: MS-DOS
+ Preparation.
+
+ There is not a lot of preparatory work that needs to be
+ done to successfully install from one of Walnut Creek's
+ FreeBSD CDROMs (other CDROM distributions may work as
+ well, but I can't say for sure as I have no hand or say
+ in their creation). You can either boot into the CD
+ installation directly from MS-DOS using Walnut Creek's
+ supplied "install" batch file or you can make a boot
+ floppy by writing the supplied image
+ (floppies/boot.flp) onto a floppy with the "go"
+ command, which invokes the rawrite.exe command found in
+ the tools/ subdirectory.
+
+ If you're creating the boot floppy from a UNIX machine,
+ you may find that ``dd if=floppies/boot.flp
+ of=/dev/rfd0'' or ``dd if=floppies/boot.flp
+ of=/dev/floppy'' works well, depending on your hardware
+ and operating system environment.
+
+ Once you've booted from MS-DOS or floppy, you should be
+ able to select CDROM as the media type in the Media
+ menu and load the entire distribution from CDROM. No
+ other types of installation media should be required.
+
+ After your system is fully installed and you have
+ rebooted from the hard disk, you should find the CD
+ mounted on the directory /cdrom. A utility called
+ `lndir' comes with the XFree86 distribution which you
+ may also find useful: It allows you to create "link
+ tree" directories to things on Read-Only media like
+ CDROM. One example might be something like this:
+ <tscreen>mkdir /usr/ports<newline>lndir /cdrom/ports
+ /usr/ports</tscreen>
+
+ Which would allow you to then "cd /usr/ports; make" and
+ get all the sources from the CD, but yet create all the
+ intermediate files in /usr/ports, which is presumably
+ on a more writable media!
+
+
+ <sect1><heading>Before installing from Floppy</heading>
+
+ <p>If you must install from floppy disks, either due to
+ unsupported hardware or just because you enjoy doing
+ things the hard way, you must first prepare some
+ floppies for the install.
+
+ The first floppy you'll need is ``floppies/root.flp'',
+ which is somewhat special in that it's not a MS-DOS
+ filesystem floppy at all, but rather an "image" floppy
+ (it's actually a gzip'd cpio file). You can use the
+ rawrite.exe program to do this under DOS, or ``dd'' to
+ do it on a UNIX Workstation (see notes in section 2.1
+ concerning the ``floppies/boot.flp'' image). Once this
+ floppy is made, put it aside. You'll be asked for it
+ later.
+
+ You will also need, at minimum, as many 1.44MB or 1.2MB
+ floppies as it takes to hold all files in the bin
+ (binary distribution) directory. THESE floppies *must*
+ be formatted using MS-DOS, using with the FORMAT
+ command in MS-DOS or the File Manager format command in
+ Microsoft Windows(tm). Factory preformatted floppies
+ will also work well, provided that they haven't been
+ previously used for something else.
+
+ Many problems reported by our users in the past have
+ resulted from the use of improperly formatted media, so
+ we simply take special care to mention it here!
+
+ After you've MS-DOS formatted the floppies, you'll need
+ to copy the files onto them. The distribution files
+ are split into chunks conveniently sized so that 5 of
+ them will fit on a conventional 1.44MB floppy. Go
+ through all your floppies, packing as many files as
+ will fit on each one, until you've got all the
+ distributions you want packed up in this fashion.
+ Select ``Floppy'' from the Media menu at installation
+ time and you will be prompted for everything after
+ that.
+
+
+ <sect1><heading>Before installing from a MS-DOS partition</heading>
+
+ <p>To prepare for installation from an MS-DOS partition,
+ copy the files from the distribution into a directory
+ called <tt>C:&bsol;FREEBSD</tt>. The directory tree structure
+ of the CDROM must be partially reproduced within this directory
+ so we suggest using the DOS <tt>xcopy</tt>
+ command. For example, to prepare for a minimal installation of
+ FreeBSD:
+<tscreen><verb>
+C> MD C:\FREEBSD
+C> XCOPY /S E:\FLOPPIES C:\FREEBSD\FLOPPIES\
+C> XCOPY /S E:\DISTS\BIN C:\FREEBSD\BIN\
+</verb></tscreen>
+ asssuming that <tt>C:</tt> is where you have free space
+ and <tt>E:</tt> is where your CDROM is mounted. Note
+ that you need the <tt>FLOPPIES</tt> directory because
+ the <tt>root.flp</tt> image is needed during an MS-DOS
+ installation.
+
+ For as many `DISTS' you wish to install from MS-DOS
+ (and you have free space for), install each one under
+ <tt>C:&bsol;FREEBSD</tt> - the <tt>BIN</tt> dist is only the
+ minimal requirement. If you have room on your MS-DOS
+ partition for all the distributions, you could replace
+ the last line above with:
+<tscreen><verb>
+C> XCOPY /S E:\DISTS C:\FREEBSD\
+</verb></tscreen>
+ which would copy all the subdirectories of
+ <tt>E:&bsol;DISTS</tt> to <tt>C:&bsol;FREEBSD</tt>.
+
+ <sect1><heading>Before installing from QIC/SCSI Tape</heading>
+
+ <p>Installing from tape is probably the easiest method,
+ short of an on-line install using FTP or a CDROM
+ instal. The installation program expects the files to
+ be simply tar'ed onto the tape, so after getting all of
+ the files for distribution you're interested in, simply
+ tar them onto the tape with a command like:
+<tscreen>
+ cd /freebsd/distdir<newline>
+ tar cvf /dev/rwt0 (or /dev/rst0) dist1 .. dist2
+ </tscreen>
+ Make sure that the `floppies/' directory is one of the
+ "dists" given above, since the installation will look
+ for `floppies/root.flp' on the tape.
+
+ When you go to do the installation, you should also
+ make sure that you leave enough room in some temporary
+ directory (which you'll be allowed to choose) to
+ accommodate the FULL contents of the tape you've
+ created. Due to the non-random access nature of tapes,
+ this method of installation requires quite a bit of
+ temporary storage! You should expect to require as
+ much temporary storage as you have stuff written on
+ tape.
+
+
+<sect1><heading>Before installing over a network</heading>
+
+ <p>You can do network installations over 3 types of
+ communications links:
+ <descrip>
+ <tag>Serial port</tag> SLIP or PPP <tag>Parallel
+ port</tag> PLIP (laplink cable) <tag>Ethernet</tag> A
+ standard ethernet controller (includes some PCMCIA).
+ </descrip>
+
+ SLIP support is rather primitive, and limited primarily
+ to hard-wired links, such as a serial cable running
+ between a laptop computer and another computer. The link
+ should be hard-wired as the SLIP installation doesn't
+ currently offer a dialing capability; that facility is
+ provided with the PPP utility, which should be used in
+ preference to SLIP whenever possible.
+
+ If you're using a modem, then PPP is almost certainly
+ your only choice. Make sure that you have your service
+ provider's information handy as you'll need to know it
+ fairly soon in the installation process. You will need
+ to know, at the minimum, your service provider's IP
+ address and possibly your own (though you can also leave
+ it blank and allow PPP to negotiate it with your ISP).
+ You also need to know how to use the various "AT
+ commands" to dial the ISP with your particular modem as
+ the PPP dialer provides only a very simple terminal
+ emulator.
+
+ If a hard-wired connection to another FreeBSD (2.0R or
+ later) machine is available, you might also consider
+ installing over a "laplink" parallel port cable. The
+ data rate over the parallel port is much higher than is
+ what's typically possible over a serial line (up to
+ 50k/sec), thus resulting in a quicker installation.
+
+ Finally, for the fastest possible network installation,
+ an ethernet adaptor is always a good choice! FreeBSD
+ supports most common PC ethernet cards, a table of
+ supported cards (and their required settings) provided as
+ part of the FreeBSD Hardware Guide - see the
+ Documentation menu on the boot floppy. If you are using
+ one of the supported PCMCIA ethernet cards, also be sure
+ that it's plugged in _before_ the laptop is powered on!
+ FreeBSD does not, unfortunately, currently support "hot
+ insertion" of PCMCIA cards.
+
+ You will also need to know your IP address on the
+ network, the "netmask" value for your address class and
+ the name of your machine. Your system administrator can
+ tell you which values to use for your particular network
+ setup. If you will be referring to other hosts by name
+ rather than IP address, you'll also need a name server
+ and possibly the address of a gateway (if you're using
+ PPP, it's your provider's IP address) to use in talking
+ to it. If you do not know the answers to all or most of
+ these questions, then you should really probably talk to
+ your system administrator _first_ before trying this type
+ of installation!
+
+ Once you have a network link of some sort working, the
+ installation can continue over NFS or FTP.
+
+ <sect2><heading>Preparing for NFS installation</heading>
+
+ <p>NFS installation is fairly straight-forward: Simply
+ copy the FreeBSD distribution files you're interested
+ onto a server somewhere and then point the NFS media
+ selection at it.
+
+ If this server supports only "privileged port" access
+ (as is generally the default for Sun workstations),
+ you will need to set this option in the Options menu
+ before installation can proceed.
+
+ If you have a poor quality ethernet card which
+ suffers from very slow transfer rates, you may also
+ wish to toggle the appropriate Options flag.
+
+ In order for NFS installation to work, the server
+ must support "subdir mounts", e.g. if your FreeBSD
+ 2.0.5 distribution directory lives on:
+ ziggy:/usr/archive/stuff/FreeBSD Then ziggy will have
+ to allow the direct mounting of
+ /usr/archive/stuff/FreeBSD, not just /usr or
+ /usr/archive/stuff.
+
+ In FreeBSD's /etc/exports file, this is controlled by
+ the ``-alldirs'' option. Other NFS servers may have
+ different conventions. If you are getting
+ `Permission Denied' messages from the server then
+ it's likely that you don't have this enabled
+ properly!
+
+
+ <sect2><heading>Preparing for FTP Installation</heading>
+
+ <p>FTP installation may be done from any mirror site
+ containing a reasonably up-to-date version of FreeBSD
+ 2.0.5, a full menu of reasonable choices from almost
+ anywhere in the world being provided by the FTP site
+ menu.
+
+ If you are installing from some other FTP site not
+ listed in this menu, or you are having troubles
+ getting your name server configured properly, you can
+ also specify your own URL by selecting the ``Other''
+ choice in that menu. A URL can also be a direct IP
+ address, so the following would work in the absence
+ of a name server: <tscreen>
+ ftp://192.216.222.4/pub/FreeBSD/2.0.5-RELEASE</tscreen>
+
+ <em><bf>NOTE:</bf> Substitute "ALPHA" for "RELEASE"
+ during the ALPHA test period!</em>
+
+ If you are installing through a firewall then you
+ should probably select ``Passive mode'' ftp, which is
+ the default. If you are talking to a server which
+ does not support passive mode for some reason, see
+ the Options menu to select Active mode transfers.
+
+
+ <sect><heading>Installing FreeBSD</heading>
+
+ <p>Once you've taken note of the appropriate
+ preinstallation steps, you should be able to install
+ FreeBSD without any further trouble.
+
+ Should this not be true, then you may wish to go back and
+ re-read the relevant preparation section (section 2.x)
+ for the installation media type you're trying to use -
+ perhaps there's a helpful hint there that you missed the
+ first time? If you're having hardware trouble, or
+ FreeBSD refuses to boot at all, read the Hardware Guide
+ provided on the boot floppy for a list of possible
+ solutions.
+
+ The FreeBSD boot floppy contains all the on-line
+ documentation you should need to be able to navigate
+ through an installation and if it doesn't then I'd like
+ to know what you found most confusing! It is the
+ objective of the FreeBSD installation program
+ (sysinstall) to be self-documenting enough that painful
+ "step-by-step" guides are no longer necessary. It may
+ take us a little while to reach that objective, but
+ that's the objective!
+
+ Meanwhile, you may also find the following "typical
+ installation sequence" to be helpful:
+
+ <enum>
+
+ <item>Boot the boot floppy. After a boot sequence
+ which can take anywhere from from 30 seconds to 3
+ minutes, depending on your hardware, you should be
+ presented with a menu of initial choices. If the
+ floppy doesn't boot at all, or the boot hangs at some
+ stage, go read the Q&amp;A section of the Hardware Guide
+ for possible causes.
+
+ <item>Press F1. You should see some basic usage
+ instructions on the menu system and general
+ navigation. If you haven't used this menu system
+ before then PLEASE read this thoroughly!
+
+ <item>If English is not your native language, you may
+ wish to proceed directly to the Language option and
+ set your preferred language. This will bring up some
+ of the documentation in that language instead of
+ english.
+
+ <item>Select the Options item and set any special
+ preferences you may have.
+
+ <item>Select Proceed, bringing you to the Installation Menu.
+
+ </enum>
+
+ <sect1><heading>The installation menu</heading>
+
+ <p>You can do anything you like in this menu without
+ altering your system <em>except</em> for "Commit",
+ which will perform any requests to alter your system
+ you may have made.
+
+ If you're confused at any point, the F1 key usually
+ pulls up the right information for the screen you're
+ in.
+
+ <enum>
+
+ <item>The first step is generally `Partition', which
+ allows you to chose how your drives will be used
+ for FreeBSD.
+
+ <item>Next, with the `Label' editor, you can specify
+ how the space in any allocated FreeBSD partitions
+ should be used by FreeBSD, or where to mount a
+ non-FreeBSD partition (such as DOS).
+
+ <item>Next, the `Distributions' menu allows you to
+ specify which parts of FreeBSD you wish to load. A
+ good choice is "User" for a small system or
+ "Developer" for someone wanting a bit more out of
+ FreeBSD. If none of the existing collections sound
+ applicable, select Custom.
+
+ <item>Next, the `Media' menu allows you to specify
+ what kind of media you wish to install from. If a
+ desired media choice is found and configured
+ automatically then this menu will simply return,
+ otherwise you'll be asked for additional details on
+ the media device type.
+
+ <item>Finally, the Commit command will actually
+ perform all the actions at once (nothing has been
+ written to your disk so far, nor will it until you
+ give the final confirmation). All new or changed
+ partition information will be written out, file
+ systems will be created and/or non-destructively
+ labelled (depending on how you set their newfs
+ flags in the Label editor) and all selected
+ distributions will be extracted.
+
+ <item>The Configure menu choice allows you to furthur
+ configure your FreeBSD installation by giving you
+ menu-driven access to various system defaults.
+ Some items, like networking, may be especially
+ important if you did a CDROM/Tape/Floppy
+ installation and have not yet configured your
+ network interfaces (assuming you have some).
+ Properly configuring your network here will allow
+ FreeBSD to come up on the network when you first
+ reboot from the hard disk.
+
+ <item>Exit returns you to the top menu.
+
+ </enum>
+
+ At this point, you're generally done with the
+ sysinstall utility and can select the final `Quit'. If
+ you're running it as an installer (e.g. before the
+ system is all the way up) then the system will now
+ reboot. If you selected the boot manager option, you
+ will see a small boot menu with an `F?' prompt. Press
+ the function key for BSD (it will be shown) and you
+ should boot up into FreeBSD off the hard disk.
+
+ If this fails to happen for some reason, see the Q&amp;A
+ section of the Hardware Guide for possible clues!
+
diff --git a/share/doc/handbook/kerneldebug.sgml b/share/doc/handbook/kerneldebug.sgml
new file mode 100644
index 0000000000000..6afbd419bbb87
--- /dev/null
+++ b/share/doc/handbook/kerneldebug.sgml
@@ -0,0 +1,425 @@
+<!-- $Id: kerneldebug.sgml,v 1.2 1995/06/30 17:37:41 jfieber Exp $ -->
+<!-- The FreeBSD Documentation Project -->
+
+<chapt><heading>Kernel Debugging<label id="kerneldebug"></heading>
+
+<p><em>Contributed by &a.paul; and &a.joerg;</em>
+
+<sect><heading>Debugging a kernel crash dump with kgdb</heading>
+
+ <p>Here are some instructions for getting kernel debugging
+ working on a crash dump, it assumes that you have enough swap
+ space for a crash dump. If you have multiple swap
+ partitions and the first one is too small to hold the dump,
+ you can configure your kernel to use an alternate dump device
+ (in the <tt>config kernel</tt> line), or
+ you can specify an alternate using the dumpon(8) command.
+ Dumps to non-swap devices,
+ tapes for example, are currently not supported. Config your
+ kernel using <tt>config -g</tt>.
+ See <ref id="kernelconfig" name="Kernel Configuration"> for
+ details on configuring the FreeBSD kernel.
+
+ Use the <tt>dumpon(8)</tt> command to tell the kernel where to dump
+ to (note that this will have to be done after configuring the
+ partition in question as swap space via <tt>swapon(8)</tt>). This is
+ normally arranged via <tt>/etc/sysconfig</tt> and <tt>/etc/rc</tt>.
+ Alternatively, you can
+ hard-code the dump device via the `dump' clause in the `config' line
+ of your kernel config file. This is deprecated, but might be the
+ only chance to get a crash dump from a kernel that's not booting at
+ all, so that you didn't had the ability to run any command before it
+ used to crash.
+
+ <em><bf>Note:</bf> In the following, the term `<tt>kgdb</tt>' refers
+ to <tt>gdb</tt> run in `kernel debug mode'. This can be accomplished by
+ either starting the <tt>gdb</tt> with the option <tt>-k</tt>, or by linking
+ and starting it under the name <tt>kgdb</tt>. This is not being
+ done by default, however.</em>
+
+ When the kernel has been built make a copy of it, say
+ <tt>kernel.debug</tt>, and then run <tt>strip -x</tt> on the
+ original. Install the original as normal. You may also install
+ the unstripped kernel, but symbol table lookup time for some
+ programs will drastically increase, and since
+ the whole kernel is loaded entirely at boot time and cannot be
+ swapped out later, several megabytes of
+ physical RAM willl be wasted.
+
+ If you are testing a new kernel, for example by typing the new
+ kernel's name at the boot prompt, but need to boot a different
+ one in order to get your system up and running again, boot it
+ only into single user state using the <tt>-s</tt> flag at the
+ boot prompt, and then perform the following steps:
+<tscreen><verb>
+ fsck -p
+ mount -a -t ufs # so your file system for /var/crash is writable
+ savecore -N /kernel.panicked /var/crash
+ exit # ...to multi-user
+</verb></tscreen>
+ This instructs <tt>savecore(8)</tt> to use another kernel for symbol name
+ extraction. It would otherwise default to the currently running kernel.
+
+ Now, after a crash dump, go to <tt>/sys/compile/WHATEVER</tt> and run
+ <tt>kgdb</tt>. From <tt>kgdb</tt> do:
+<tscreen><verb>
+ symbol-file kernel.debug
+ exec-file /var/crash/system.0
+ core-file /var/crash/ram.0
+</verb></tscreen>
+ and voila, you can debug the crash dump using the kernel sources
+ just like you can for any other program.
+
+ If your kernel panicked due to a trap, perhaps the most common
+ case for getting a core dump, the following trick might help
+ you. Examine the stack using <tt>kgdb</tt>'s `where' command,
+ and look for the stack frame in the function <tt>trap()</tt>. Go `up'
+ to that frame, and then type:
+<tscreen><verb>
+ frame frame->tf_ebp frame->tf_eip
+</verb></tscreen>
+ This will tell <tt>kgdb</tt> to go to the stack frame explicitly named by a
+ frame pointer and instruction pointer, which is the location where
+ the trap occured. There are still some bugs in <tt>kgdb</tt> (you can go
+ `up' from there, but not `down'; the stack trace will still remain
+ as it was before going to here), but generally this method will lead
+ you much closer to the failing piece of code.
+
+ Here's a script log of a <tt>kgdb</tt> session illustrating the above. Long
+ lines have been folded to improve readability, and the lines are
+ numbered for reference. Despite of this, it's a real-world error
+ trace taken during the development of the pcvt console driver.
+<tscreen><verb>
+ 1:Script started on Fri Dec 30 23:15:22 1994
+ 2:uriah # cd /sys/compile/URIAH
+ 3:uriah # kgdb kernel /var/crash/vmcore.1
+ 4:Reading symbol data from /usr/src/sys/compile/URIAH/kernel...done.
+ 5:IdlePTD 1f3000
+ 6:panic: because you said to!
+ 7:current pcb at 1e3f70
+ 8:Reading in symbols for ../../i386/i386/machdep.c...done.
+ 9:(kgdb) where
+ 10:#0 boot (arghowto=256) (../../i386/i386/machdep.c line 767)
+ 11:#1 0xf0115159 in panic ()
+ 12:#2 0xf01955bd in diediedie () (../../i386/i386/machdep.c line 698)
+ 13:#3 0xf010185e in db_fncall ()
+ 14:#4 0xf0101586 in db_command (-266509132, -266509516, -267381073)
+ 15:#5 0xf0101711 in db_command_loop ()
+ 16:#6 0xf01040a0 in db_trap ()
+ 17:#7 0xf0192976 in kdb_trap (12, 0, -272630436, -266743723)
+ 18:#8 0xf019d2eb in trap_fatal (...)
+ 19:#9 0xf019ce60 in trap_pfault (...)
+ 20:#10 0xf019cb2f in trap (...)
+ 21:#11 0xf01932a1 in exception:calltrap ()
+ 22:#12 0xf0191503 in cnopen (...)
+ 23:#13 0xf0132c34 in spec_open ()
+ 24:#14 0xf012d014 in vn_open ()
+ 25:#15 0xf012a183 in open ()
+ 26:#16 0xf019d4eb in syscall (...)
+ 27:(kgdb) up 10
+ 28:Reading in symbols for ../../i386/i386/trap.c...done.
+ 29:#10 0xf019cb2f in trap (frame={tf_es = -260440048, tf_ds = 16, tf_\
+ 30:edi = 3072, tf_esi = -266445372, tf_ebp = -272630356, tf_isp = -27\
+ 31:2630396, tf_ebx = -266427884, tf_edx = 12, tf_ecx = -266427884, tf\
+ 32:_eax = 64772224, tf_trapno = 12, tf_err = -272695296, tf_eip = -26\
+ 33:6672343, tf_cs = -266469368, tf_eflags = 66066, tf_esp = 3072, tf_\
+ 34:ss = -266427884}) (../../i386/i386/trap.c line 283)
+ 35:283 (void) trap_pfault(&amp;frame, FALSE);
+ 36:(kgdb) frame frame->tf_ebp frame->tf_eip
+ 37:Reading in symbols for ../../i386/isa/pcvt/pcvt_drv.c...done.
+ 38:#0 0xf01ae729 in pcopen (dev=3072, flag=3, mode=8192, p=(struct p\
+ 39:roc *) 0xf07c0c00) (../../i386/isa/pcvt/pcvt_drv.c line 403)
+ 40:403 return ((*linesw[tp->t_line].l_open)(dev, tp));
+ 41:(kgdb) list
+ 42:398
+ 43:399 tp->t_state |= TS_CARR_ON;
+ 44:400 tp->t_cflag |= CLOCAL; /* cannot be a modem (:-) */
+ 45:401
+ 46:402 #if PCVT_NETBSD || (PCVT_FREEBSD >= 200)
+ 47:403 return ((*linesw[tp->t_line].l_open)(dev, tp));
+ 48:404 #else
+ 49:405 return ((*linesw[tp->t_line].l_open)(dev, tp, flag));
+ 50:406 #endif /* PCVT_NETBSD || (PCVT_FREEBSD >= 200) */
+ 51:407 }
+ 52:(kgdb) print tp
+ 53:Reading in symbols for ../../i386/i386/cons.c...done.
+ 54:$1 = (struct tty *) 0x1bae
+ 55:(kgdb) print tp->t_line
+ 56:$2 = 1767990816
+ 57:(kgdb) up
+ 58:#1 0xf0191503 in cnopen (dev=0x00000000, flag=3, mode=8192, p=(st\
+ 59:ruct proc *) 0xf07c0c00) (../../i386/i386/cons.c line 126)
+ 60: return ((*cdevsw[major(dev)].d_open)(dev, flag, mode, p));
+ 61:(kgdb) up
+ 62:#2 0xf0132c34 in spec_open ()
+ 63:(kgdb) up
+ 64:#3 0xf012d014 in vn_open ()
+ 65:(kgdb) up
+ 66:#4 0xf012a183 in open ()
+ 67:(kgdb) up
+ 68:#5 0xf019d4eb in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi =\
+ 69: 2158592, tf_esi = 0, tf_ebp = -272638436, tf_isp = -272629788, tf\
+ 70:_ebx = 7086, tf_edx = 1, tf_ecx = 0, tf_eax = 5, tf_trapno = 582, \
+ 71:tf_err = 582, tf_eip = 75749, tf_cs = 31, tf_eflags = 582, tf_esp \
+ 72:= -272638456, tf_ss = 39}) (../../i386/i386/trap.c line 673)
+ 73:673 error = (*callp->sy_call)(p, args, rval);
+ 74:(kgdb) up
+ 75:Initial frame selected; you cannot go up.
+ 76:(kgdb) quit
+ 77:uriah # exit
+ 78:exit
+ 79:
+ 80:Script done on Fri Dec 30 23:18:04 1994
+</verb></tscreen>
+ Comments to the above script:
+
+<descrip>
+<tag/line 6:/ This is a dump taken from within DDB (see below), hence the
+ panic comment ``because you said to!'', and a rather long
+ stack trace; the initial reason for going into DDB has been
+ a page fault trap though.
+<tag/line 20:/ This is the location of function <tt>trap()</tt>
+ in the stack trace.
+<tag/line 36:/ Force usage of a new stack frame, kgdb responds and displays
+ the source line where the trap happened; from looking at the
+ code, there's a high probability that either the pointer
+ access for ``tp'' was messed up, or the array access was
+ out of bounds.
+<tag/line 52:/ The pointer looks suspicious, but happens to be a valid
+ address.
+<tag/line 56:/ However, it obviously points to garbage, so we have found our
+ error! (For those unfamiliar with that particular piece
+ of code: <tt>tp-&gt;t_line</tt> refers to the line discipline
+ of the console device here, which must be a rather small integer
+ number.)
+</descrip>
+
+
+<sect><heading>Post-mortem analysis of a dump</heading>
+
+<p>What do you do if a kernel dumped core but you did not expect
+ it, and it's therefore not compiled using <tt>config -g</tt>?
+ Not everything is lost here. Don't panic!
+
+ Of course, you still need to enable crash dumps. See above
+ on the options you've got to do this.
+ (This is for safety reasons in the default kernels, to avoid them
+ trying to dump e.g. during system installation where there's no
+ FreeBSD partition at all and valuable data on the disk could be
+ destroyed.)
+
+ Go to your kernel compile directory, and edit the line
+ containing <tt>COPTFLAGS?=-O</tt>. Add the <tt>-g</tt> option
+ there (but <em>don't</em> change anything on the level of
+ optimization). If you do already know roughly the probable
+ location of the failing piece of code (e.g., the <tt>pcvt</tt>
+ driver in the example above), remove all the object files for
+ this code. Rebuild the kernel. Due to the time stamp change on
+ the Makefile, there will be some other object files rebuild,
+ for example <tt>trap.o</tt>. With a bit of luck, the added
+ <tt>-g</tt> option won't change anything for the generated
+ code, so you'll finally get a new kernel with similiar code to
+ the faulting one but some debugging symbols. You should at
+ least verify the old and new sizes with the <tt>size(1)</tt> command. If
+ there is a mismatch, you probably need to give up here.
+
+ Go and examine the dump as described above. The debugging
+ symbols might be incomplete for some places, as can be seen in
+ the stack trace in the example above where some functions are
+ displayed without line numbers and argument lists. If you need
+ more debugging symbols, remove the appropriate object files and
+ repeat the <tt>kgdb</tt> session until you know enough.
+
+ All this is not guaranteed to work, but it will do it fine in
+ most cases.
+
+<sect><heading>On-line kernel debugging using DDB</heading>
+
+<p>While <tt>kgdb</tt> as an offline debugger provides a very
+ high level of user interface, there are some things it cannot do.
+ The most important ones being breakpointing and single-stepping
+ kernel code.
+
+ If you need to do low-level debugging on your kernel, there's
+ an on- line debugger available called DDB. It allows to
+ setting breakpoints, single-steping kernel functions, examining
+ and changeing kernel variables, etc. However, it cannot not
+ access kernel source files, and only has access to the global
+ and static symbols, not to the full debug information like
+ <tt>kgdb</tt>.
+
+ To configure your kernel to include DDB, add the option line
+<tscreen><verb>
+ options DDB
+</verb></tscreen>
+ to your config file, and rebuild. (See <ref id="kernelconfig"
+ name="Kernel Configuration"> for details on configuring the
+ FreeBSD kernel. Note that if you have an older version of the
+ boot blocks, your debugger symbols might not be loaded at all.
+ Update the boot blocks, the recent ones do load the DDB symbols
+ automagically.)
+
+ Once your DDB kernel is running, there are several ways to
+ enter DDB. The first, and earliest way is to type the boot
+ flag <tt>-d</tt> right at the boot prompt. The kernel will
+ start up in debug mode and enter DDB prior to any device
+ probing. Hence you are able to even debug the device
+ probe/attach functions.
+
+ The second scenario is a hot-key on the keyboard, usually
+ Ctrl-Alt-ESC. For syscons, this can be remapped, and some of
+ the distributed maps do this, so watch out.
+ There's an option
+ available for a COMCONSOLE kernel (``options BREAK_TO_DEBUGGER'')
+ that allows the use of a serial line BREAK on the console line to
+ enter DDB.
+
+ The third way is that any panic condition will branch to DDB if
+ the kernel is configured to use it. It is not wise to
+ configure a kernel with DDB for a machine running unattended
+ for this reason.
+
+ The DDB commands roughly resemble some <tt>gdb</tt> commands. The first you
+ probably need is to set a breakpoint:
+<tscreen><verb>
+ b function-name
+ b address
+</verb></tscreen>
+
+ Numbers are taken hexadecimal by default, but to make them
+ distinct from symbol names, hexadecimal numbers starting with the
+ letters <tt>a</tt>-<tt>f</tt> need to be preceded with
+ <tt>0x</tt> (for other numbers, this is optional). Simple
+ expressions are allowed, for example: <tt>function-name + 0x103</tt>.
+
+ To continue the operation of an interrupted kernel, simply type
+<tscreen><verb>
+ c
+</verb></tscreen>
+ To get a stack trace, use
+<tscreen><verb>
+ trace
+</verb></tscreen>
+ Note that when entering DDB via a hot-key, the kernel is currently
+ servicing an interrupt, so the stack trace might be not of much use
+ for you.
+
+ If you want to remove a breakpoint, use
+<tscreen><verb>
+ del
+ del address-expression
+</verb></tscreen>
+ The first form will be accepted immediately after a breakpoint hit,
+ and deletes the current breakpoint. The second form can remove any
+ breakpoint, but you need to specify the exact address, as it can be
+ obtained from
+<tscreen><verb>
+ show b
+</verb></tscreen>
+ To single-step the kernel, try
+<tscreen><verb>
+ s
+</verb></tscreen>
+ This will step into functions, but you can make DDB trace them until
+ the matching return statement is reached by
+<tscreen><verb>
+ n
+</verb></tscreen>
+ Note: this is different from <tt>gdb</tt>'s `next' statement, it's like
+ <tt>gdb</tt>'s `finish'.
+
+ To examine data from memory, use (for example):
+<tscreen><verb>
+ x/wx 0xf0133fe0,40
+ x/hd db_symtab_space
+ x/bc termbuf,10
+ x/s stringbuf
+</verb></tscreen>
+ for word/halfword/byte access, and hexadecimal/decimal/character/
+ string display. The number after the comma is the object count.
+ To display the next 0x10 items, simply use
+<tscreen><verb>
+ x ,10
+</verb></tscreen>
+ Similiarly, use
+<tscreen><verb>
+ x/ia foofunc,10
+</verb></tscreen>
+ to disassemble the first 0x10 instructions of <tt>foofunc</tt>, and display
+ them along with their offset from the beginning of <tt>foofunc</tt>.
+
+ To modify the memory, use the write command:
+<tscreen><verb>
+ w/b termbuf 0xa 0xb 0
+ w/w 0xf0010030 0 0
+</verb></tscreen>
+ The command modifier (<tt>b</tt>/<tt>h</tt>/<tt>w</tt>)
+ specifies the size of the data to be writtten, the first
+ following expression is the address to write to, the remainder
+ is interpreted as data to write to successive memory locations.
+
+ If you need to know the current registers, use
+<tscreen><verb>
+ show reg
+</verb></tscreen>
+ Alternatively, you can display a single register value by e.g.
+<tscreen><verb>
+ print $eax
+</verb></tscreen>
+ and modify it by
+<tscreen><verb>
+ set $eax new-value
+</verb></tscreen>
+
+ Should you need to call some kernel functions from DDB, simply
+ say
+<tscreen><verb>
+ call func(arg1, arg2, ...)
+</verb></tscreen>
+ The return value will be printed.
+
+ For a <tt>ps(1)</tt> style summary of all running processes, use
+<tscreen><verb>
+ ps
+</verb></tscreen>
+
+ Now you have now examined why your kernel failed, and you wish to
+ reboot. Remember that, depending on the severity of previous
+ malfunctioning, not all parts of the kernel might still be working
+ as expected. Perform one of the following actions to shut down and
+ reboot your system:
+<tscreen><verb>
+ call diediedie()
+</verb></tscreen>
+
+ will cause your kernel to dump core and reboot, so you can
+ later analyze the core on a higher level with kgdb. This
+ command usually must be followed by another
+ `<tt>continue</tt>' statement.
+ There is now an alias for this: `<tt>panic</tt>'.
+
+<tscreen><verb>
+ call boot(0)
+</verb></tscreen>
+ might be a good way to cleanly shut down the running system, <tt>sync()</tt>
+ all disks, and finally reboot. As long as the disk and file system
+ interfaces of the kernel are not damaged, this might be a good way
+ for an almost clean shutdown.
+
+<tscreen><verb>
+ call cpu_reset()
+</verb></tscreen>
+ is the final way out of disaster and almost the same as hitting
+ the Big Red Button.
+
+
+
+<sect><heading>Debugging a console driver</heading>
+
+<p>Since you need a console driver to run DDB on, things are more
+ complicated if the console driver itself is flakey. You might
+ remember the <tt>options COMCONSOLE</tt> line, and hook up a standard
+ terminal onto your first serial port. DDB works on any configured
+ console driver, of course it also works on a <tt>COMCONSOLE</tt>.
+
+
diff --git a/share/doc/handbook/relnotes.sgml b/share/doc/handbook/relnotes.sgml
new file mode 100644
index 0000000000000..d85f2992ccefd
--- /dev/null
+++ b/share/doc/handbook/relnotes.sgml
@@ -0,0 +1,503 @@
+<!-- $Id: relnotes.sgml,v 1.3 1995/06/30 17:37:47 jfieber Exp $ -->
+<!-- The FreeBSD Documentation Project -->
+
+<!--
+<!DOCTYPE linuxdoc PUBLIC '-//FreeBSD//DTD linuxdoc//EN'>
+<linuxdoc><book><chapt>foo
+-->
+ <sect><heading>About this release<label id="relnotes"></heading>
+
+ <p>Since our first release of FreeBSD 1.0 nearly two
+ years ago, FreeBSD has changed dramatically. Since
+ release 2.0, FreeBSD has been based on the Berkeley BSD
+ 4.4-lite code rather than the Net2 code used for
+ previous versions. In addition to clearing the legal
+ issues that surrounded the Net2 code, the port to 4.4
+ has also brought in numerous new features, filesystems
+ and enhanced driver support.
+
+ Since our release of FreeBSD 2.0 in November of 1994,
+ the performance, feature set, and stability of FreeBSD
+ has improved dramatically. The largest change is a
+ revamped Virtual Memory (VM) system with a merged
+ virtual memory and file buffer cache. This increases
+ performance while reducing FreeBSD's memory footprint,
+ making a system with 4 megabytes of RAM a more
+ acceptable minimum. Other enhancements include full
+ NIS client and server support, transaction TCP support,
+ dial on demand PPP, an improved SCSI subsystem, early
+ support for ISDN, support for FDDI and 100Mbit Fast
+ Ethernet adapters, improved support for the Adaptec
+ 2940 and hundreds of bug fixes.
+
+ We've also taken the comments and suggestions of many
+ of our users to heart and have attempted to provide
+ what we hope is a more sane and easily understood
+ installation process. Your feedback on this constantly
+ evolving process is especially welcome!
+
+ In addition to the base distributions, FreeBSD offers a
+ new ported software collection with some 270 commonly
+ sought-after programs. The list of ports ranges from
+ World Wide Web (http) servers, to games, languages,
+ editors and almost everything in between. The entire
+ ports collection requires only 10MB of storage because
+ each port contains only the changes required for the
+ source code to compile on FreeBSD and the information
+ necessary to automatically retrieve the original
+ sources. The original distribution for each port you
+ build is automatically retrieved off of CD-ROM or a via
+ anonymous ftp, so you need only enough disk space to
+ build the ports you want. Each port is also provided
+ as a pre-compiled package which can be installed with
+ the <tt>pkg_add(1)</tt> command for those who do not
+ wish to compile their own ports from source. See <ref
+ id="ports" name="The Ports Collection"> for a more
+ complete description.
+
+<!-- XXX make xref
+ For a list of contributors and a general project
+ description, please see the file "CONTRIB.FreeBSD"
+ which should be bundled with your binary distribution.
+
+ Also see the "REGISTER.FreeBSD" file for information on
+ registering with the "Free BSD user counter". This
+ counter is for ALL freely available variants of BSD,
+ not just FreeBSD, and we urge you to register yourself
+ with it.
+-->
+
+ The core of FreeBSD does not contain DES code which
+ would inhibit its being exported outside the United
+ States. An add-on package, for use only in the United
+ States, contains the programs that normally use DES.
+ The auxiliary packages provided separately can be used
+ by anyone. A freely exportable European distribution
+ of DES for our non-U.S. users also exists and is
+ described in the <url
+ url="http://www.freebsd.org/How/faq" name="FreeBSD
+ FAQ">. If password security for FreeBSD is all you
+ need, and you have no requirement for copying encrypted
+ passwords from other hosts using DES into FreeBSD
+ password entries, then FreeBSD's MD5 based security may
+ be all you require. We feel that our default security
+ model is more than a match for DES, and without any
+ messy export issues to deal with.
+
+ FreeBSD 2.0.5 represents the culmination of 2 years of
+ work and many thousands of man hours put in by an
+ international development team. We hope you enjoy it!
+
+ <sect1><heading>New feature highlights</heading>
+
+ <p>The following features were added or substantially
+ improved between the release of 2.0 and this 2.0.5
+ release. In order to facilitate better
+ communication, the person, or persons, responsible
+ for each enhancement is noted. Any questions
+ regarding the new functionality should be directed to
+ them first.
+
+ <sect2><heading>Kernel</heading>
+
+ <p>
+ <descrip>
+
+ <tag>Merged VM-File Buffer Cache</tag> A merged
+ VM/buffer cache design greatly enhances overall
+ system performance and makes it possible to do
+ a number of more optimal memory allocation
+ strategies that were not possible before.
+
+ Owner: David Greenman (davidg@FreeBSD.org) and
+ John Dyson (dyson@implode.root.com)
+
+ <tag>Network PCB hash optimization</tag> For
+ systems with a great number of active TCP
+ connections (WEB and ftp servers, for example),
+ this greatly speeds up the lookup time required
+ to match an incoming packet up to its
+ associated connection.
+
+ Owner: David Greenman (davidg@FreeBSD.org)
+
+ <tag>Name cache optimization</tag> The name-cache
+ would cache all files of the same name to the
+ same bucket, which would put for instance all
+ ".." entries in the same bucket. We added the
+ parent directory version to frustrate the hash,
+ and improved the management of the cache in
+ various other ways while we were at it.
+
+ Owner: Poul-Henning Kamp (phk@FreeBSD.org)
+ David Greenman (davidg@FreeBSD.org)
+
+ <tag>Less restrictive swap-spaces</tag> The need
+ to compile the names of the swap devices into
+ the kernel has been removed. Now
+ <tt>swapon(8)</tt> will accept any block
+ devices, up to the maximum number of swap
+ devices configured in the kernel.
+
+ Owner: Poul-Henning Kamp (phk@FreeBSD.org)
+ David Greenman (davidg@FreeBSD.org)
+
+ <tag>Hard Wired SCSI Devices</tag> Prior to
+ 2.0.5, FreeBSD performed dynamic assignment of
+ unit numbers to SCSI devices as they were
+ probed, allowing a SCSI device failure to
+ possibly change unit number assignment. This
+ could cause filesystems other disks in the
+ system to be incorrectly mounted, or not
+ mounted at all. Hard wiring allows static
+ allocation of unit numbers (and hence device
+ names) to scsi devices based on SCSI ID and
+ bus. SCSI configuration occurs in the kernel
+ config file. Samples of the configuration
+ syntax can be found in the <tt>scsi(4)</tt> man
+ page or the LINT kernel config file.
+
+ Owner: Peter Dufault (dufault@hda.com)
+
+ Sources involved: <tt>sys/scsi/*</tt>
+ <tt>usr.sbin/config/*</tt>
+
+ <tag>Slice Support</tag> FreeBSD now supports a
+ <em>slice</em> abstraction which enhances
+ FreeBSD's ability to share disks with other
+ operating systems. This support will allow
+ FreeBSD to inhabit DOS extended partitions.
+
+ Owner: Bruce Evans (bde@FreeBSD.org)
+
+ Sources involved: <tt>sys/disklabel.h</tt>
+ <tt>sys/diskslice.h</tt> <tt>sys/dkbad.h</tt>
+ <tt>kern/subr_diskslice.c</tt> <tt>kern/subr_dkbad.c</tt>
+ <tt>i386/isa/diskslice_machdep.c</tt> <tt>i386/isa/wd.c</tt>
+ <tt>scsi/sd.c</tt> <tt>dev/vn/vn.c</tt>
+
+ <tag>Support for Ontrack Disk Manager Version
+ 6.0</tag> Support has been added for disks
+ which use Ontrack Disk Manager. The fdisk
+ program does <em>not</em> know about it
+ however, so make all changes using the install
+ program on the boot.flp or the Ontrack Disk
+ Manager tool under MS-DOS.
+
+ Owner: Poul-Henning Kamp (phk@FreeBSD.org)
+
+ <tag>Bad144 is back and working</tag> Bad144
+ works again, though the semantics are slightly
+ different than before in that the bad-spots are
+ kept relative to the slice rather than absolute
+ on the disk.
+
+ Owner: Bruce Evans (bde@FreeBSD.org)
+ Poul-Henning Kamp (phk@FreeBSD.org)
+
+ </descrip>
+
+ <sect2><heading>New device support</heading>
+
+ <sect3><heading>SCSI and CDROM devices</heading>
+
+ <p><descrip>
+
+ <tag>Matsushita/Panasonic (Creative) CD-ROM
+ driver</tag> The Matsushita/Panasonic CR-562 and
+ CR-563 drives are now supported when connected to
+ a Sound Blaster or 100% compatible host adapter.
+ Up to four host adapters are supported for a
+ total of 16 CD-ROM drives. The audio functions
+ are supported with the Karoke variable speed
+ playback.
+
+ Owner: Frank Durda IV
+ (bsdmail@nemesis.lonestar.org)
+
+ Sources involved: <tt>isa/matcd</tt>
+
+ <tag>Adaptec 2742/2842/2940 SCSI driver</tag> The
+ original 274x/284x driver has evolved
+ considerably since the 2.0 release of FreeBSD.
+ We now offer full support for the 2940 series as
+ well as the Wide models of these cards. The
+ arbitration bug that caused problems with fast
+ devices has been corrected and
+ <em>experimental</em> tagged queuing support has
+ been added (kernel option
+ <tt>AHC_TAGENABLE</tt>). John Aycock has also
+ released the sequencer code under a Berkeley
+ style copyright making the driver entirely clean
+ of the GPL.
+
+ Owner: Justin Gibbs (gibbs@FreeBSD.org)
+
+ Sources involved: <tt>isa/aic7770.c</tt> <tt>pci/aic7870.c</tt>
+ <tt>i386/scsi/*</tt> <tt>sys/dev/aic7xxx/*</tt>
+
+ <tag>NCR5380/NCR53400 SCSI (ProAudio Spectrum)
+ driver</tag> Owner: core
+
+ Submitted by: Serge Vakulenko (vak@cronyx.ru)
+
+ Sources involved: <tt>isa/ncr5380.c</tt>
+
+ <tag>Sony CDROM driver</tag> Owner: core
+
+ Submitted by: Mikael Hybsch (micke@dynas.se)
+
+ Sources involved: <tt>isa/scd.c</tt>
+
+ </descrip>
+
+ <sect3><heading>Serial devices</heading>
+
+ <p><descrip>
+
+ <tag>SDL Communications Riscom/8 Serial Board
+ Driver</tag> Owner: Andrey Chernov
+ (ache@FreeBSD.org)
+
+ Sources involved: <tt>isa/rc.c</tt> <tt>isa/rcreg.h</tt>
+
+ <tag>Cyclades Cyclom-y Serial Board Driver</tag>
+ Owner: Bruce Evans (bde@FreeBSD.org)
+
+ Submitted by: Andrew Werple
+ (andrew@werple.apana.org.au) and Heikki Suonsivu
+ (hsu@cs.hut.fi)
+
+ Obtained from: NetBSD
+
+ Sources involved: <tt>isa/cy.c</tt>
+
+ <tag>Cronyx/Sigma sync/async serial driver</tag>
+ Owner: core
+
+ Submitted by: Serge Vakulenko
+
+ Sources involved: <tt>isa/cronyx.c</tt>
+
+ </descrip>
+
+ <sect2><heading>Networking</heading>
+
+ <p><descrip>
+
+ <tag>Diskless booting</tag> Diskless booting in 2.0.5
+ is much improved over previous releases. The boot
+ program is in <tt>src/sys/i386/boot/netboot</tt>,
+ and can be run from an MS-DOS system or burned into
+ an EPROM. WD, SMC, 3COM and Novell ethernet cards
+ are currently supported. Local swapping is also
+ supported.
+
+ <tag>DEC DC21140 Fast Ethernet driver</tag> This
+ driver supports any of the numerous NICs using the
+ DC21140 chipset including the 100Mb DEC DE-500-XA
+ and SMC 9332.
+
+ Owner: core
+
+ Submitted by: Matt Thomas (thomas@lkg.dec.com)
+
+ Sources involved: <tt>pci/if_de.c</tt> <tt>pci/dc21040.h</tt>
+
+
+ <tag>DEC FDDI (DEFPA/DEFEA) driver</tag> Owner: core
+
+ Submitted by: Matt Thomas (thomas@lkg.dec.com)
+
+ Sources involved: <tt>pci/if_pdq.c</tt> <tt>pci/pdq.c</tt>
+ <tt>pci/pdq_os.h</tt> <tt>pci/pdqreg.h</tt>
+
+
+ <tag>3Com 3c505 (Etherlink/+) NIC driver</tag> Owner:
+ core
+
+ Submitted by: Dean Huxley (dean@fsa.ca)
+
+ Obtained from: NetBSD
+
+ Sources involved: <tt>isa/if_eg.c</tt>
+
+
+ <tag>Fujitsu MB86960A family of NICs driver</tag>
+ Owner: core
+
+ Submitted by: M.S. (seki@sysrap.cs.fujitsu.co.jp)
+
+ Sources involved: <tt>isa/if_fe.c</tt>
+
+
+ <tag>Intel EtherExpress driver</tag> Owner: Rodney
+ W. Grimes (rgrimes@FreeBSD.org)
+
+ Sources involved: <tt>isa/if_ix.c</tt> <tt>isa/if_ixreg.h</tt>
+
+
+ <tag>3Com 3c589 driver</tag> Owner: core
+
+ Submitted by: "HOSOKAWA Tatsumi"
+ (hosokawa@mt.cs.keio.ac.jp), Seiji Murata
+ (seiji@mt.cs.keio.ac.jp) and Noriyuki Takahashi
+ (hor@aecl.ntt.jp)
+
+ Sources involved: <tt>isa/if_zp.c</tt>
+
+
+ <tag>IBM Credit Card Adapter driver</tag> Owner: core
+
+ Submitted by: "HOSOKAWA Tatsumi"
+ (hosokawa@mt.cs.keio.ac.jp),
+
+ Sources involved: <tt>isa/pcic.c</tt> <tt>isa/pcic.h</tt>
+
+
+ <tag>EDSS1 and 1TR6 ISDN interface driver</tag>
+ Owner: core
+
+ Submitted by: Dietmar Friede
+ (dfriede@drnhh.neuhaus.de) and Juergen Krause
+ (jkr@saarlink.de)
+
+ Sources involved: <tt>gnu/isdn/*</tt>
+
+ </descrip>
+
+ <sect2><heading>Miscellaneous drivers</heading>
+
+ <p><descrip>
+
+ <tag>Joystick driver</tag> Owner: Jean-Marc Zucconi
+ (jmz@FreeBSD.org)
+
+ Sources involved: <tt>isa/joy.c</tt>
+
+ <tag>National Instruments "LabPC" driver</tag> Owner:
+ Peter Dufault (dufault@hda.com)
+
+ Sources involved: <tt>isa/labpc.c</tt>
+
+ <tag>WD7000 driver</tag> Owner: Olof Johansson
+ (offe@ludd.luth.se)
+
+ <tag>Pcvt Console driver</tag> Owner: Joerg Wunsch
+ (joerg@FreeBSD.org)
+
+ Submitted by: Hellmuth Michaelis
+ (hm@altona.hamburg.com)
+
+ Sources involved: <tt>isa/pcvt/*</tt>
+
+ <tag>BSD-audio emulator for VAT driver</tag> Owner:
+ Amancio Hasty (ahasty@FreeBSD.org) and
+ Paul Traina (pst@FreeBSD.org)
+
+ Sources involved: <tt>isa/sound/vat_audio.c</tt>
+ <tt>isa/sound/vat_audioio.h</tt>
+
+ <tag>National Instruments AT-GPIB and AT-GPIB/TNT
+ GPIB driver</tag> Owner: core
+
+ Submitted by: Fred Cawthorne
+ (fcawth@delphi.umd.edu)
+
+ Sources involved: <tt>isa/gpib.c</tt> <tt>isa/gpib.h</tt>
+ <tt>isa/gpibreg.h</tt>
+
+ <tag>Genius GS-4500 hand scanner driver</tag> Owner:
+ core
+
+ Submitted by: Gunther Schadow
+ (gusw@fub46.zedat.fu-berlin.de)
+
+ Sources involved: <tt>isa/gsc.c</tt> <tt>isa/gscreg.h</tt>
+
+ <tag>CORTEX-I Frame Grabber</tag> Owner: core
+
+ Submitted by: Paul S. LaFollette, Jr. (
+
+ Sources involved: <tt>isa/ctx.c</tt> <tt>isa/ctxreg.h</tt>
+
+
+ <tag>Video Spigot video capture card</tag> Owner: Jim
+ Lowe
+
+ </descrip>
+
+ <sect1><heading>Experimental features</heading>
+
+ <p><descrip>
+
+ <tag>UNIONFS and LFS</tag> The unionfs and LFS file
+ systems are known to be severely broken in FreeBSD
+ 2.0.5. This is in part due to old bugs that we
+ haven't had time to resolve yet and the need to
+ update these file systems to deal with the new VM
+ system. We hope to address these issues in a later
+ release of FreeBSD.
+
+ <tag>iBCS2 Support</tag> FreeBSD now supports running
+ iBCS2 compatible binaries. Currently SCO UNIX 3.2.2
+ and 3.2.4, and ISC 2.2 COFF are supported. The iBCS2
+ emulator is in its early stages and has not been
+ extensively tested, but it is functional. Most of
+ SCO's 3.2.2 binaries work, as does an old
+ INFORMIX-2.10 for SCO. Further testing is nessesary
+ to complete this project. There is also work under
+ way for ELF and XOUT loaders, and most of the svr4
+ syscall wrappers are written.
+
+ Owner: Soren Schmidt (sos) and Sean Eric Fagan (sef)
+
+ Sources involved: <tt>sys/i386/ibcs2/*</tt> and misc
+ kernel changes.
+
+ </descrip>
+<!--
+ <sect1><heading>Reporting problems, making suggestions, submitting code</heading>
+
+ <p>Your suggestions, bug reports and contributions of code
+ are always valued - please do not hesitate to report any
+ problems you may find (preferably with a fix attached if
+ you can!).
+
+ The preferred method to submit bug reports from a machine
+ with internet mail connectivity is to use the send-pr
+ command. Bug reports will be dutifully filed by our
+ faithful bugfiler program and you can be sure that we'll
+ do our best to respond to all reported bugs as soon as
+ possible.
+
+ If, for some reason, you are unable to use the send-pr
+ command to submit a bug report, you can try to send it
+ to: <tscreen>bugs@FreeBSD.org</tscreen> Otherwise, for
+ any questions or suggestions, please send mail to:
+ <tscreen>questions@FreeBSD.org</tscreen>
+
+ Additionally, being a volunteer effort, we are always
+ happy to have extra hands willing to help - there are
+ already far more enhancements to be done than we can ever
+ manage to do by ourselves! To contact us on technical
+ matters, or with offers of help, you may send mail to:
+ <tscreen>hackers@FreeBSD.org</tscreen>
+
+ Since these mailing lists can experience significant
+ amounts of traffic, if you have slow or expensive mail
+ access and you are only interested in keeping up with
+ significant FreeBSD events, you may find it preferable to
+ subscribe to: <tscreen>announce@FreeBSD.org</tscreen>
+
+ All but the freebsd-bugs groups can be freely joined by
+ anyone wishing to do so. Send mail to
+ MajorDomo@FreeBSD.org and include the keyword `help' on a
+ line by itself somewhere in the body of the message.
+ This will give you more information on joining the
+ various lists, accessing archives, etc. There are a
+ number of mailing lists targeted at special interest
+ groups not mentioned here, so send mail to majordomo and
+ ask about them!
+
+-->
diff --git a/share/doc/handbook/userppp.sgml b/share/doc/handbook/userppp.sgml
new file mode 100644
index 0000000000000..cd1c50cdc66db
--- /dev/null
+++ b/share/doc/handbook/userppp.sgml
@@ -0,0 +1,360 @@
+<!-- $Id: userppp.sgml,v 1.2 1995/08/19 22:16:06 jfieber Exp $ -->
+<!-- The FreeBSD Documentation Project -->
+
+<sect>Setting up user PPP<label id="userppp">
+
+<p><em>Contributed by &a.nik;<newline>
+28 July 1995</em>.
+
+<!-- This FAQ/HowTo is intended to get you up and running with
+ iijppp, also known as the <em>user level ppp</em> for FreeBSD 2.0.5
+ (and above).
+
+ I hope this document turns into a collaborative effort, largely
+ because I am not really much of an authority on PPP. I've got
+ it working, and want to pass on details of what I did so that
+ other people can get it working. But I'm not 100% clear on some
+ details, so I hope that by writing this and haveing others
+ flesh out some of the information I'm going to learn something
+ as well.
+-->
+
+ <p>User PPP was intruduced to FreeBSD in release 2.0.5 as an
+ addition to the exisiting kernel implementation of PPP. So,
+ what is different about this new PPP that warrants its
+ addition? To quote from the manual page:
+
+<quote>
+ This is a user process PPP software package. Normally, PPP is
+ implemented as a part of the kernel (e.g. as managed by pppd) and
+ it's thus somewhat hard to debug and/or modify its behavior. However,
+ in this implementation PPP is done as a user process with the help of
+ the tunnel device driver (tun).
+</quote>
+
+ In essence, this means that rather than running a PPP daemon, the ppp
+ program can be run as and when desired. No PPP interface needs to be
+ compiled into the kernel, as the program can use the generic tunnel
+ device to to get data into and out of the kernel.
+
+ From here on out, user ppp will be referred to as simply as ppp unless a
+ distinction need to be made be it and any other PPP client/server software.
+ Unless otherwise stated, all commands in this section should be
+ executed as root.
+
+ Parts in this section marked with an asterisk (*) are
+ incomplete. Comments and suggestions are appreciated and
+ should be submitted to &a.nik;.
+ Thanks to Rob Snow &lt;rsnow@txdirect.net&gt; who proved to be a mine of
+ useful information when I was first experimenting with user ppp.
+
+<sect1><heading>Before you start</heading>
+
+<p>This document assumes you're in roughly this position:
+
+ You have an account with an Internet Service Provider (ISP) which lets you
+ use PPP. Further, you have a modem (or other device) connected and
+ configured correctly which allows you to connect to your ISP.
+
+ You are going to need the following information to hand:
+
+<itemize>
+ <item>IP address of your ISP's gateway
+
+ <item>Your ISP's netmask setting
+
+ <item>IP adresses of one or more nameservers
+
+ <item>If your ISP allocates you a static IP address and/or hostname then
+ you will need that as well. If not, you will need to know from what
+ range of IP addresses your allocated IP address will fall in.
+</itemize>
+
+ If you do not have any of this information then contact your ISP and make
+ sure they provide it to you.
+
+ As well as this, you may need the files required to recompile
+ your kernel. Check <ref id="kernelconfig" name="Kernel
+ Configuration"> for more information on how to acquire these.
+
+ In addition, I've assumed that because your connection to the Internet is
+ not full time you are not running a name server (<tt>named(8)</tt>).
+
+<sect1><heading>Building a ppp ready kernel</heading>
+
+<p>As the description states, ``ppp'' uses the kernel ``tun'' device. It is
+ necessary to make sure that your kernel has support for this device compiled
+ in.
+
+ To check this, go to your kernel compile directory (probably /sys/i386/conf)
+ and examine your kernel configuration file. It needs to have the line
+<tscreen><verb>
+pseudo-device tun 1
+</verb></tscreen>
+ in it somewhere. The stock GENERIC kernel has this as standard, so if you
+ have not installed a custom kernel you don't have to change anything.
+ If your kernel configuration file does not have this line in it then you
+ should add the line, re-compile and then re-install the kernel. Boot from
+ this new kernel.
+
+<sect1><heading>Check the tun device</heading>
+
+<p>My experiences with ppp have only been with one ``tun'' device (tun0). If
+ you have used more (i.e., a number other than `1' in the pseudo-device line
+ in the kernel configuration file) then alter all references to ``tun0''
+ below to reflect whichever device number you are using.
+
+ The easiest way to make sure that the tun0 device is configured correctly is
+ to re-make it. To this end, execute the following commands,
+<tscreen><verb>
+# cd /dev
+# ./MAKEDEV tun0
+</verb></tscreen>
+
+<sect1><heading>PPP Configuration</heading>
+
+<p>The meat of the problem.
+
+ Confusingly, it appears that both user ppp and pppd (the kernel level
+ implementation of PPP) both assume configuration files kept in
+ /etc/ppp. However, the sample configuration files provided are good for
+ user ppp, so keep them around for reference. The easiest way to do this is,
+<tscreen><verb>
+# cd /etc
+# mv ppp ppp.orig
+# mkdir ppp
+</verb></tscreen>
+ Configuring ppp requires that you edit somewhere between one and three
+ files, depending on your requirements. What you put in them depends to some
+ extent on whether your ISP allocates IP addresses statically (i.e., you get
+ given one IP address, and always use that one) or dynamically (i.e., your IP
+ address can be different during different PPP sessions).
+
+ However, there are a few things that you should do first, regardless of
+ whether you are using static or dynamic IP addresses.
+
+
+<sect2><heading>Configure the resolver(5)</heading>
+
+<p>The resolver is the part of the networking system that turns IP addresses
+ into hostnames. It can be configured to look for maps that describe IP to
+ hostname mappings in one of two places.
+
+ The first is a file called /etc/hosts (``hosts'' in section 5 of the
+ manual). The second is the Internet Domain Name Service, a distributed
+ data base, the discussion of which is beyond the realm of this document.
+
+ The resolver is a set of system calls that do the mappings,
+ and you have to tell them where to get their information
+ from. You do this by editing the file /etc/host.conf. Do
+ <bf>not</bf> call this file /etc/hosts.conf (note the extra
+ ``s'') as the results can be confusing.
+
+ This file should contain the following two lines,
+<tscreen><verb>
+hosts
+bind
+</verb></tscreen>
+ which instruct the resolver to look in the file /etc/hosts first, and
+ then to consult the DNS if the name was not found in the /etc/hosts file.
+
+ It's probably a good idea to make sure you are not running the ``named''
+ service. Check your /etc/sysconfig file for the line that refers to
+ ``namedflags'', and make sure the line reads
+<tscreen><verb>
+namedflags="NO"
+</verb></tscreen>
+
+<sect2><heading>Create the /etc/hosts(5) file</heading>
+
+<p>This file should contain the IP addresses and names of machines on your
+ network. At a bare minimum it should contain entries for the machine
+ which will be running ppp. Assuming that you're machine is called
+ foo.bar.com with the IP address 10.0.0.1, /etc/hosts should contain
+<tscreen><verb>
+127.0.0.0 localhost
+10.0.0.1 foo.bar.com foo
+</verb></tscreen>
+ The first line defines the alias ``localhost'' as a synonym for the
+ current machine. Regardless of your own IP address, the IP address for
+ this line should always be 127.0.0.1. The second line maps the name
+ ``foo.bar.com'' (and the shorthand ``foo'') to the IP address 10.0.0.1.
+
+ If your provider allocates you a static IP address then use this in place
+ of 10.0.0.1.
+
+ <!-- XXX <em>(* What should they do if they are
+ allocated an IP address dynamically?)</em> -->
+
+<sect2><heading>Create the /etc/resolv.conf file</heading>
+
+<p>/etc/resolv.conf contains some extra information required when you are
+ not running a nameserver. It points the resolver routines at real
+ nameservers, and specifies some other information.
+
+ At the very least, /etc/resolv.conf should contain one line with a
+ nameserver which can be queried. You should enter this as an IP
+ address. My /etc/resolv.conf contains
+<tscreen><verb>
+nameserver 158.152.1.193
+nameserver 158.152.1.65
+</verb></tscreen>
+ Which are Demon Internet's two nameservers. Add as many ``nameserver''
+ lines as your ISP provides nameservers.
+
+<sect1><heading>PPP and static IP addresses</heading>
+
+<p>Probably the easiest to configure for. You will need to create three files
+ in the /etc/ppp directory.
+
+ The first of these is ppp.conf. It should look similar to the example
+ below. Note that lines that end in a ``:'' start in column 1, all other
+ lines should be indented as shown.
+
+ /etc/ppp/ppp.conf
+<tscreen><verb>
+1 default:
+2 set device /dev/cuaa0
+3 set speed 9600
+4 disable lqr
+5 deny lqr
+6 set dial "ABORT BUSY ABORT NO\\sCARRIER TIMEOUT 5 \"\" ATE1Q0 OK-AT-OK
+\\dATDT\\T TIMEOUT 40 CONNECT"
+7 provider:
+8 set phone 01234567890
+9 set login "TIMEOUT 10 gin:-BREAK-gin: foo word: bar col: ppp"
+10 set timeout 120
+11 set ifaddr x.x.x.x y.y.y.y
+</verb></tscreen>
+ Don't include the line numbers, they're just for this discussion.
+
+<descrip>
+<tag/Line 1:/ Identifies the default entry. Commands in this entry are
+ executed automatically when ppp is run.
+
+<tag/Line 2:/ Identifies the device that has the modem hanging from it.
+ COM1: is /dev/cuaa0 and COM2: is /dev/cuaa1
+
+<tag/Line 3:/ Sets the speed you want to connect at.
+
+<tag/* Lines 4 and 5:/ Don't know exactly what effect these lines have
+
+<tag/Line 6:/ Dial string commands. user ppp uses the chat(8) language. Check
+ the manual page for information on the features of this
+ language.
+
+<tag/Line 7:/ Identifies an entry for a provider called ``provider''.
+
+<tag/Line 8:/ Sets the phone number for this provider. Don't include any
+ spaces in the phone number.
+
+<tag/Line 9:/ Set's the login string sequence. In this example, the string is
+ for a service who's login session looks like
+<tscreen><verb>
+J. Random Provider
+login: foo
+password: bar
+protocol: ppp
+</verb></tscreen>
+ You will need to alter this script to suit your own needs. It is
+ written in the chat(8) language.
+
+<tag/Line 10:/ Sets the default timeout (in seconds) for the connection. So
+ the connectioned will be closed automatically after 120 seconds
+ of inactivity.
+
+<tag/Line 11:/ Sets the interface addresses. The string x.x.x.x should be
+ replaced by the IP address that your provider allocates you. The
+ string y.y.y.y should be replaced by the IP address that your
+ ISP indicated for their gateway.
+</descrip>
+
+ Now you have to edit the file /etc/ppp/ppp.linkup:
+<tscreen><verb>
+x.x.x.x:
+ add 0 0 HISADDR
+</verb></tscreen>
+ Replace x.x.x.x with your IP address as before. This file is used to
+ automatically add a default route from your ISP (who's address is
+ automatically inserted with the HISADDR macro) to you.
+
+ Finally, you can create the file /etc/ppp/ppp.secret, which sets some
+ passwords to prevent people messing around with ppp on your system. You
+ may or may not want to do this, depending on how many people have access
+ to your ppp system.
+
+<sect1><heading>PPP and Dynamic IP configuration</heading>
+
+<!-- XXX -->
+ <p>If you service provider does not assign static IP numbers,
+ <tt>ppp</tt> can be configured to negotiate the local address. This is
+ done by specifying 0 as the local IP address:
+<tscreen><verb>
+set ifaddr 0 0
+</verb></tscreen>
+ See the <tt>ppp(8)</tt> manual page for more detailed information.
+
+<sect1><heading>Final system configuration</heading>
+
+<p>You now have PPP configured, but there's a few more things to do before
+ it's ready to work. They all involve editing the /etc/sysconfig file.
+
+ Working from the top down in this file, make sure the ``hostname='' line
+ is set, e.g.,
+<tscreen><verb>
+hostname=foo.bar.com
+</verb></tscreen>
+ Look for the network_interfaces variable, and make sure the tun0 device is
+ added to the list. My line looks like
+<tscreen><verb>
+network_interfaces="lo0 tun0 ep0"
+</verb></tscreen>
+ but I have an ethernet card (ep0) to configure as well.
+
+ Now add an ifconfig line for the tun0 device. It should look something
+ like
+<tscreen><verb>
+ifconfig_tun0="inet foo.bar.com y.y.y.y netmask 0xffffffff"
+</verb></tscreen>
+ as before, change ``foo.bar.com'' to be your hostname, y.y.y.y is the IP
+ address of your providers gateway, and 0xffffffff is the netmask they
+ provided you with (in hexadecimal). Two common values for the netmask are
+<tscreen><verb>
+255.255.255.255 = 0xffffffff
+255.255.255.0 = 0xffffff00
+</verb></tscreen>
+ Set the routed flags to ``-s'' with the line
+<tscreen><verb>
+routedflags=-s
+</verb></tscreen>
+ It's probably worth your while ensuring that the ``sendmail_flags'' line
+ does not include the ``-q'' option, otherwise sendmail will attempt to do
+ a network lookup every now and then, possibly causing your machine to dial
+ out. My sendmail line looks like
+<tscreen><verb>
+sendmail_flags="-bd"
+</verb></tscreen>
+ The upshot of this is that I must force sendmail to re-examine the
+ mailqueue whenever I have the PPP link up, by typing
+<tscreen><verb>
+# /usr/sbin/sendmail -q
+</verb></tscreen>
+ That should be about all you need to do to get PPP working with a static
+ IP address. All that's left is to reboot the machine. During startup the
+ tun0 device should be detected, and two lines like the following should be
+ printed,
+<tscreen><verb>
+tun0: flags=51<UP,POINTOPOINT,RUNNING> mtu 1500
+inet x.x.x.x --> y.y.y.y netmask 0xffffffff
+</verb></tscreen>
+ At this point, it should all be working. You can now either type
+<tscreen><verb>
+# ppp
+</verb></tscreen>
+ and then ``dial provider'' to start the PPP session, or, if you want ppp
+ to establish sessions automatically when there is outbound traffic, type
+<tscreen><verb>
+# ppp -auto provider
+</verb></tscreen>
+ This line could be added to your /etc/rc.local file.
+
diff --git a/share/examples/find_interface/Makefile b/share/examples/find_interface/Makefile
new file mode 100644
index 0000000000000..fcc330cc19496
--- /dev/null
+++ b/share/examples/find_interface/Makefile
@@ -0,0 +1,6 @@
+# $Id$
+
+PROG= find_interface
+NOMAN=
+
+.include <bsd.prog.mk>
diff --git a/share/examples/find_interface/README b/share/examples/find_interface/README
new file mode 100644
index 0000000000000..4df4399cdbc7b
--- /dev/null
+++ b/share/examples/find_interface/README
@@ -0,0 +1,9 @@
+This is a simple program which demonstrates how to query the kernel
+routing mechanism using only a UDP socket. Pass it a hostname on
+the command line (sorry, it doesn't parse dotted decimal) and it will
+print out an IP address which names the interface over which UDP
+packets intended for that destination would be sent.
+A more sophisticated program might use the list obtained from SIOCGIFCONF
+to match the address with an interface name, but applications programmers
+much more often need to know the address of the interface rather than
+the name.
diff --git a/share/syscons/keymaps/spanish.iso.kbd b/share/syscons/keymaps/spanish.iso.kbd
new file mode 100644
index 0000000000000..584941a5311ff
--- /dev/null
+++ b/share/syscons/keymaps/spanish.iso.kbd
@@ -0,0 +1,109 @@
+# alt
+# scan cntrl alt alt cntrl lock
+# code base shift cntrl shift alt shift cntrl shift state
+# ------------------------------------------------------------------
+ 000 nop nop nop nop nop nop nop nop O
+ 001 esc esc esc esc esc esc esc esc O
+ 002 '1' '!' nop nop '|' '|' nop nop O
+ 003 '2' '"' nul nul '@' '@' nul nul O
+ 004 '3' 183 nop nop '#' '#' nop nop O
+ 005 '4' '$' nop nop '4' '4' nop nop O
+ 006 '5' '%' nop nop '5' '5' nop nop O
+ 007 '6' '&' rs rs 172 172 rs rs O
+ 008 '7' '/' esc esc '7' '7' esc esc O
+ 009 '8' '(' nop nop '8' '8' nop nop O
+ 010 '9' ')' gs gs '8' '8' gs gs O
+ 011 '0' '=' nop nop '9' '9' nop nop O
+ 012 ''' '?' nop nop ''' ''' nop nop O
+ 013 161 191 nop nop ''' '`' nop nop O
+ 014 bs bs del del bs bs del del O
+ 015 ht btab nop nop ht btab nop nop O
+ 016 'q' 'Q' dc1 dc1 'q' 'Q' dc1 dc1 C
+ 017 'w' 'W' etb etb 'w' 'W' etb etb C
+ 018 'e' 'E' enq enq 233 201 enq enq C
+ 019 'r' 'R' dc2 dc2 'r' 'R' dc2 dc2 C
+ 020 't' 'T' dc4 dc4 't' 'T' dc4 dc4 C
+ 021 'y' 'Y' em em 'y' 'Y' sub sub C
+ 022 'u' 'U' nak nak 250 218 nak nak C
+ 023 'i' 'I' ht ht 237 205 ht ht C
+ 024 'o' 'O' si si 243 211 si si C
+ 025 'p' 'P' dle dle 'p' 'P' dle dle C
+ 026 '`' '^' esc esc '[' '[' esc esc C
+ 027 '+' '*' gs gs ']' '[' gs gs O
+ 028 cr cr nl nl cr cr nl nl O
+ 029 lctrl lctrl lctrl lctrl lctrl lctrl lctrl lctrl O
+ 030 'a' 'A' soh soh 225 193 soh soh C
+ 031 's' 'S' dc3 dc3 's' 'S' dc3 dc3 C
+ 032 'd' 'D' eot eot 'd' 'D' eot eot C
+ 033 'f' 'F' ack ack 'f' 'F' ack ack C
+ 034 'g' 'G' bel bel 'g' 'G' bel bel C
+ 035 'h' 'H' bs bs 'h' 'H' bs bs C
+ 036 'j' 'J' nl nl 'j' 'J' nl nl C
+ 037 'k' 'K' vt vt 'k' 'K' vt vt C
+ 038 'l' 'L' ff ff 'l' 'L' ff ff C
+ 039 241 209 nop nop '~' nop nop nop C
+ 040 252 220 nop nop '{' 220 nop nop C
+ 041 186 170 fs fs '\' '\' fs fs O
+ 042 lshift lshift lshift lshift lshift lshift lshift lshift O
+ 043 231 199 rs rs '}' '}' rs rs O
+ 044 'z' 'Z' sub sub 'z' 'Z' em em C
+ 045 'x' 'X' can can 'x' 'X' can can C
+ 046 'c' 'C' etx etx 'c' 'C' etx etx C
+ 047 'v' 'V' syn syn 'v' 'V' syn syn C
+ 048 'b' 'B' stx stx 'b' 'B' stx stx C
+ 049 'n' 'N' so so 'n' 'N' so so C
+ 050 'm' 'M' cr cr 'm' 'M' cr cr C
+ 051 ',' ';' nop nop ',' ';' nop nop O
+ 052 '.' ':' nop nop '.' ':' nop nop O
+ 053 '-' '_' ns ns '-' '_' ns ns O
+ 054 rshift rshift rshift rshift rshift rshift rshift rshift O
+ 055 '*' '*' nscr nscr '*' '*' nscr nscr O
+ 056 lalt lalt lalt lalt lalt lalt lalt lalt O
+ 057 ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' O
+ 058 clock clock clock clock clock clock clock clock O
+ 059 fkey01 fkey13 fkey25 fkey37 scr01 scr11 scr01 scr11 O
+ 060 fkey02 fkey14 fkey26 fkey38 scr02 scr12 scr02 scr12 O
+ 061 fkey03 fkey15 fkey27 fkey39 scr03 scr13 scr03 scr13 O
+ 062 fkey04 fkey16 fkey28 fkey40 scr04 scr14 scr04 scr14 O
+ 063 fkey05 fkey17 fkey29 fkey41 scr05 scr15 scr05 scr15 O
+ 064 fkey06 fkey18 fkey30 fkey42 scr06 scr16 scr06 scr16 O
+ 065 fkey07 fkey19 fkey31 fkey43 scr07 scr07 scr07 scr07 O
+ 066 fkey08 fkey20 fkey32 fkey44 scr08 scr08 scr08 scr08 O
+ 067 fkey09 fkey21 fkey33 fkey45 scr09 scr09 scr09 scr09 O
+ 068 fkey10 fkey22 fkey34 fkey46 scr10 scr10 scr10 scr10 O
+ 069 nlock nlock dc3 dc3 nlock nlock dc3 dc3 O
+ 070 slock slock del del slock slock del del O
+ 071 fkey49 '7' '7' '7' '7' '7' '7' '7' N
+ 072 fkey50 '8' '8' '8' '8' '8' '8' '8' N
+ 073 fkey51 '9' '9' '9' '9' '9' '9' '9' N
+ 074 fkey52 '-' ns ns '-' '-' '-' '-' N
+ 075 fkey53 '4' '4' '4' '4' '4' '4' '4' N
+ 076 fkey54 '5' '5' '5' '5' '5' '5' '5' N
+ 077 fkey55 '6' rs rs '6' '6' '6' '6' N
+ 078 fkey56 '+' '+' '+' '+' '+' '+' '+' N
+ 079 fkey57 '1' '1' '1' '1' '1' '1' '1' N
+ 080 fkey58 '2' '2' '2' '2' '2' '2' '2' N
+ 081 fkey59 '3' '3' '3' '3' '3' '3' '3' N
+ 082 fkey60 '0' '0' '0' '0' '0' '0' '0' N
+ 083 del '.' del del del del del del N
+ 084 ns ns ns ns ns ns ns ns O
+ 085 nop nop nop nop nop nop nop nop O
+ 086 '<' '>' fs fs '\' '>' fs fs O
+ 087 fkey11 fkey23 fkey35 fkey47 scr11 scr11 scr11 scr11 O
+ 088 fkey12 fkey24 fkey36 fkey48 scr12 scr12 scr12 scr12 O
+ 089 scr03 scr03 scr03 scr03 scr03 scr03 scr03 scr03 N
+ 090 rctrl rctrl rctrl rctrl rctrl rctrl rctrl rctrl O
+ 091 '/' '/' '/' '/' '/' '/' '/' '/' N
+ 092 '*' '*' '*' '*' '*' '*' '*' '*' N
+ 093 ralt ralt ralt ralt ralt ralt ralt ralt O
+ 094 fkey49 fkey49 fkey49 fkey49 fkey49 fkey49 fkey49 fkey49 O
+ 095 fkey50 fkey50 fkey50 fkey50 fkey50 fkey50 fkey50 fkey50 O
+ 096 fkey51 fkey51 fkey51 fkey51 fkey51 fkey51 fkey51 fkey51 O
+ 097 fkey53 fkey53 fkey53 fkey53 fkey53 fkey53 fkey53 fkey53 O
+ 098 fkey55 fkey55 fkey55 fkey55 fkey55 fkey55 fkey55 fkey55 O
+ 099 fkey57 fkey57 fkey57 fkey57 fkey57 fkey57 fkey57 fkey57 O
+ 100 fkey58 fkey58 fkey58 fkey58 fkey58 fkey58 fkey58 fkey58 O
+ 101 fkey59 fkey59 fkey59 fkey59 fkey59 fkey59 fkey59 fkey59 O
+ 102 fkey60 fkey60 fkey60 fkey60 fkey60 fkey60 fkey60 fkey60 O
+ 103 fkey54 fkey54 fkey54 fkey54 fkey54 fkey54 boot fkey54 O
+ 104 slock slock slock slock slock slock slock slock O
diff --git a/sys/i386/include/ioctl_meteor.h b/sys/i386/include/ioctl_meteor.h
new file mode 100644
index 0000000000000..e1fed36e5985f
--- /dev/null
+++ b/sys/i386/include/ioctl_meteor.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1995 Mark Tinguely and Jim Lowe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Tinguely and Jim Lowe
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * ioctl constants for Matrox Meteor Capture card.
+ */
+
+#ifndef _MACHINE_IOCTL_METEOR_H
+#define _MACHINE_IOCTL_METEOR_H
+
+#include <sys/ioctl.h>
+
+struct meteor_capframe {
+ short command; /* see below for valid METEORCAPFRM commands */
+ short signal; /* signal to send to the user program,
+ when a buffer is full */
+ short lowat; /* start transfer if < this number */
+ short hiwat; /* stop transfer if > this number */
+} ;
+
+/* structure for METEOR[GS]ETGEO - get/set geometry */
+struct meteor_geomet {
+ u_short rows;
+ u_short columns;
+ u_short frames;
+ u_long oformat;
+} ;
+
+/* structure for METEORGCOUNT-get count of frames, fifo errors and dma errors */
+struct meteor_counts {
+ u_long fifo_errors; /* count of fifo errors since open */
+ u_long dma_errors; /* count of dma errors since open */
+ u_long frames_captured; /* count of frames captured since open */
+} ;
+
+#define METEORCAPTUR _IOW('x', 1, int) /* capture a frame */
+#define METEORCAPFRM _IOW('x', 2, struct meteor_capframe) /* sync capture */
+#define METEORSETGEO _IOW('x', 3, struct meteor_geomet) /* set geometry */
+#define METEORGETGEO _IOR('x', 4, struct meteor_geomet) /* get geometry */
+#define METEORSTATUS _IOR('x', 5, unsigned short) /* get status */
+#define METEORSHUE _IOW('x', 6, signed char) /* set hue */
+#define METEORGHUE _IOR('x', 6, signed char) /* get hue */
+#define METEORSFMT _IOW('x', 7, unsigned long) /* set format */
+#define METEORGFMT _IOR('x', 7, unsigned long) /* get format */
+#define METEORSINPUT _IOW('x', 8, unsigned long) /* set input dev */
+#define METEORGINPUT _IOR('x', 8, unsigned long) /* get input dev */
+#define METEORSCHCV _IOW('x', 9, unsigned char) /* set uv gain */
+#define METEORGCHCV _IOR('x', 9, unsigned char) /* get uv gain */
+#define METEORSCOUNT _IOW('x',10, struct meteor_counts)
+#define METEORGCOUNT _IOR('x',10, struct meteor_counts)
+
+#define METEOR_STATUS_ID_MASK 0xf000 /* ID of 7196 */
+#define METEOR_STATUS_DIR 0x0800 /* Direction of Expansion port YUV */
+#define METEOR_STATUS_OEF 0x0200 /* Field detected: Even/Odd */
+#define METEOR_STATUS_SVP 0x0100 /* State of VRAM Port:inactive/active */
+#define METEOR_STATUS_STTC 0x0080 /* Time Constant: TV/VCR */
+#define METEOR_STATUS_HCLK 0x0040 /* Horiz PLL: locked/unlocked */
+#define METEOR_STATUS_FIDT 0x0020 /* Field detect: 50/60hz */
+#define METEOR_STATUS_ALTD 0x0002 /* Line alt: no line alt/line alt */
+#define METEOR_STATUS_CODE 0x0001 /* Colour info: no colour/colour */
+
+ /* METEORCAPTUR capture options */
+#define METEOR_CAP_SINGLE 0x0001 /* capture one frame */
+#define METEOR_CAP_CONTINOUS 0x0002 /* contiuously capture */
+#define METEOR_CAP_STOP_CONT 0x0004 /* stop the continous capture */
+
+ /* METEORCAPFRM capture commands */
+#define METEOR_CAP_N_FRAMES 0x0001 /* capture N frames */
+#define METEOR_CAP_STOP_FRAMES 0x0002 /* stop capture N frames */
+
+ /* valid video input formats: */
+#define METEOR_FMT_NTSC 0x00100 /* NTSC -- initialized default */
+#define METEOR_FMT_PAL 0x00200 /* PAL */
+#define METEOR_FMT_SECAM 0x00400 /* SECAM */
+#define METEOR_FMT_AUTOMODE 0x00800 /* auto-mode */
+#define METEOR_INPUT_DEV0 0x01000 /* camera input 0 -- default */
+#define METEOR_INPUT_DEV_RCA METEOR_GEO_DEV0
+#define METEOR_INPUT_DEV1 0x02000 /* camera input 1 */
+#define METEOR_INPUT_DEV2 0x04000 /* camera input 2 */
+#define METEOR_INPUT_DEV3 0x08000 /* camera input 3 */
+#define METEOR_INPUT_DEV_SVIDEO METEOR_GEO_DEV3
+
+ /* valid video output formats: */
+#define METEOR_GEO_RGB16 0x10000 /* packed -- initialized default */
+#define METEOR_GEO_RGB24 0x20000 /* RBG 24 bits packed */
+ /* internally stored in 32 bits */
+#define METEOR_GEO_YUV_PACKED 0x40000 /* 4-2-2 YUV 16 bits packed */
+#define METEOR_GEO_YUV_PLANER 0x80000 /* 4-2-2 YUV 16 bits planer */
+
+ /* following structure is used to coordinate the syncronous */
+
+struct meteor_mem {
+ /* kernel write only */
+ int frame_size; /* row*columns*depth */
+ unsigned num_bufs; /* number of frames in buffer (1-32) */
+ /* user and kernel change these */
+ int signal; /* signal raised to the user program,
+ on completion of frame capture */
+ int lowat; /* kernel starts capture if < this number */
+ int hiwat; /* kernel stops capture if > this number.
+ hiwat <= numbufs */
+ unsigned active; /* bit mask of active frame buffers
+ kernel sets, user clears */
+ int num_active_bufs; /* count of active frame buffer
+ kernel increments, user decrements */
+
+ /* reference to mmapped data */
+ caddr_t buf; /* The real space (virtual addr) */
+} ;
+
+#endif /* ifndef _MACHINE_IOCTL_METEOR_H */
diff --git a/sys/i386/isa/cyreg.h b/sys/i386/isa/cyreg.h
new file mode 100644
index 0000000000000..8df7294c9a944
--- /dev/null
+++ b/sys/i386/isa/cyreg.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1995 Bruce Evans.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: $
+ */
+
+/*
+ * Definitions for Cyclades Cyclom-Y serial boards.
+ */
+
+#define CY8_SVCACKR 0x100
+#define CY8_SVCACKT 0x200
+#define CY8_SVCACKM 0x300
+#define CY_CD1400_MEMSIZE 0x400
+#define CY16_RESET 0x1400
+#define CY_CLEAR_INTR 0x1800 /* intr ack address */
+
+#define CY_MAX_CD1400s 4 /* for Cyclom-16Y */
+
+#define CY_CLOCK 25000000 /* baud rate clock */
+
+#ifdef CyDebug
+#define cd_inb(iobase, reg) (++cd_inbs, *((iobase) + 2 * (reg)))
+#define cy_inb(iobase, reg) (++cy_inbs, *((iobase) + (reg)))
+#define cd_outb(iobase, reg, val) (++cd_outbs, (void)(*((iobase) + 2 * (reg)) = (val)))
+#define cy_outb(iobase, reg, val) (++cy_outbs, (void)(*((iobase) + (reg)) = (val)))
+#else
+#define cd_inb(iobase, reg) (*((iobase) + 2 * (reg)))
+#define cy_inb(iobase, reg) (*((iobase) + (reg)))
+#define cd_outb(iobase, reg, val) ((void)(*((iobase) + 2 * (reg)) = (val)))
+#define cy_outb(iobase, reg, val) ((void)(*((iobase) + (reg)) = (val)))
+#endif
diff --git a/sys/i386/isa/si_code.c b/sys/i386/isa/si_code.c
new file mode 100644
index 0000000000000..e1282eabf9827
--- /dev/null
+++ b/sys/i386/isa/si_code.c
@@ -0,0 +1,804 @@
+/*
+ * Device driver for Specialix range (SLXOS) of serial line multiplexors.
+ *
+ * Copyright (C) 1988, 1992, Specialix International,
+ * Copyright (C) 1993, Andy Rutter <andy@acronym.co.uk>
+ * Copyright (C) 1995, Peter Wemm <peter@haywire.dialix.com>
+ *
+ * Downloadable code for Z280
+ * Ported from BSDI version to FreeBSD by Peter Wemm.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notices, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Andy Rutter of
+ * Advanced Methods and Tools Ltd. based on original information
+ * from Specialix International.
+ * 4. Neither the name of Advanced Methods and Tools, nor Specialix
+ * International may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE.
+ *
+ * $Id$
+ */
+
+/*
+** @(#)download.c 1.20
+** SLXOS download code processed on Thu Aug 5 17:53:28 1993
+** (C)1992 Specialix International plc
+** All rights reserved.
+*/
+
+unsigned char
+si_download[] =
+{
+ 0x0,0xc3,0x86,0x0,0x2,0x0,0x8,0x1,0x0,0x0,
+ 0x7e,0x18,0x0,0x0,0x82,0x18,0x0,0x0,0xe4,0x1a,0x0,
+ 0x0,0xc7,0x4,0x2,0x0,0x8,0x1,0x2,0x0,0x8,0x1,
+ 0x2,0x0,0x8,0x1,0x2,0x0,0x8,0x1,0x2,0x0,0x8,
+ 0x1,0x0,0x0,0xe1,0xf,0x0,0x0,0x0,0x10,0x2,0x0,
+ 0x8,0x1,0x2,0x0,0x8,0x1,0x0,0x0,0x0,0x0,0x20,
+ 0x0,0x0,0x1,0x0,0x3c,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x3a,0x47,0x0,0xfe,0x0,0xc2,0x8,0x1,0xdd,0x3e,
+ 0x48,0x0,0x1,0x31,0xbf,0x0,0xc3,0x1e,0x13,0xff,0xff,
+ 0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0xcc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,
+ 0xcc,0xcc,0xcc,0xcc,0xcc,0x3a,0x41,0x0,0xfe,0x0,0xc2,
+ 0x1e,0x13,0x21,0x0,0x8,0xe,0xf0,0xed,0xbf,0x0,0x0,
+ 0x0,0x21,0x40,0x0,0xe,0x12,0xed,0x6e,0x3a,0x92,0x0,
+ 0xfe,0x1,0x20,0x5,0x21,0xc4,0x5,0x18,0x3,0x21,0x82,
+ 0x18,0x7d,0xe6,0xf0,0x6f,0x3e,0x0,0x46,0x23,0x3d,0xfe,
+ 0x0,0x20,0xf9,0x21,0x80,0x0,0xe,0x12,0xed,0x6e,0xdd,
+ 0x3e,0x47,0x0,0x1,0xcd,0x15,0x1,0x0,0x18,0xfe,0x0,
+ 0x0,0xdd,0xd1,0x6,0x1,0xed,0x55,0xdd,0x3e,0x0,0x0,
+ 0xfe,0x76,0xc9,0xcd,0xf9,0x1,0xfe,0x1,0x20,0x3,0xcd,
+ 0x8b,0x4,0xc9,0xe0,0x81,0x80,0x80,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8c,0x0,0xf0,
+ 0xd0,0xf0,0xd0,0x0,0xc0,0x0,0x0,0xf0,0xd0,0xf0,0xd0,
+ 0x0,0xc0,0x0,0x0,0x21,0xd,0x0,0xe,0xff,0xed,0x6e,
+ 0x21,0xf8,0x2f,0x11,0xe,0x80,0x1,0x8,0x0,0xed,0xb0,
+ 0x2a,0x43,0x0,0xe,0xff,0xed,0x6e,0xdd,0x3e,0x16,0x80,
+ 0x0,0xc9,0x79,0xfe,0x0,0x28,0x2a,0xed,0x2d,0xa0,0xff,
+ 0xed,0x2a,0x0,0x0,0x3a,0x2f,0x1,0xfe,0x40,0x20,0x7,
+ 0xfd,0xed,0xf6,0xa0,0x18,0x18,0x5,0xfd,0xed,0xf6,0xa0,
+ 0x2,0xdd,0x2a,0x24,0x1,0xed,0x2d,0x0,0x0,0xe5,0xdd,
+ 0xe1,0xdd,0x22,0x24,0x1,0x78,0x32,0x2f,0x1,0xed,0x2a,
+ 0x0,0x0,0xdd,0x1,0x0,0x0,0xdd,0x73,0x8,0xdd,0x36,
+ 0x1c,0x0,0xdd,0x36,0x1d,0x0,0x7b,0xe6,0xf,0xdd,0x77,
+ 0x2,0xdd,0x71,0x3,0xfd,0xed,0x2d,0x6,0x0,0x7b,0xe6,
+ 0xe0,0xfe,0x0,0x20,0x8,0xdd,0x36,0x4,0x0,0xfd,0x36,
+ 0x40,0xff,0xdd,0xe5,0xfd,0x7e,0x7f,0xdd,0x77,0x1e,0x3e,
+ 0x8,0xed,0x2a,0xa,0x0,0xdd,0xed,0x2a,0x60,0x1,0xdd,
+ 0xe5,0xdd,0xc1,0x3d,0x28,0xc,0xdd,0xed,0x2a,0x0,0x3,
+ 0xfd,0xed,0xf6,0x2,0x0,0x18,0xed,0xdd,0xe1,0xed,0x2a,
+ 0x0,0x0,0xfd,0xed,0xf6,0x60,0x1,0xe5,0xdd,0xe1,0xc9,
+ 0x21,0x40,0x0,0x5e,0xdd,0x11,0x2,0x80,0xff,0xff,0xdd,
+ 0x3e,0x6,0x80,0x1,0xdd,0x3e,0x82,0x80,0x0,0xdd,0x21,
+ 0x80,0x80,0xdd,0x22,0x24,0x1,0xfd,0x21,0x0,0x70,0xfd,
+ 0x22,0x28,0x1,0xe,0x0,0x16,0x1,0xe5,0x2a,0x30,0x1,
+ 0x7e,0xdd,0x13,0x30,0x1,0xe1,0xfe,0xff,0xca,0x78,0x3,
+ 0x5f,0xfe,0x4,0x28,0x10,0xfe,0x24,0x28,0xc,0x6,0x8,
+ 0xdd,0x3e,0x2e,0x1,0x8,0xcd,0x61,0x1,0x18,0xc,0x6,
+ 0x4,0xdd,0x3e,0x2e,0x1,0x4,0xcd,0x61,0x1,0x18,0x0,
+ 0x21,0xa0,0x2,0xdd,0xe,0x0,0x2b,0xfd,0xed,0xf7,0xa0,
+ 0xff,0x20,0xf5,0xfd,0xed,0x2d,0xa2,0xff,0xdd,0x36,0xc2,
+ 0xff,0x7b,0xe6,0xe0,0xdd,0x77,0xc4,0xfe,0x20,0x28,0x31,
+ 0xed,0x32,0x0,0x0,0xcb,0x9d,0xfd,0x36,0x2,0xa,0xfd,
+ 0x1e,0x4,0x0,0xe0,0xfd,0x1e,0x5,0x0,0x0,0xfd,0x1e,
+ 0x6,0x0,0x0,0xfd,0x1e,0x7,0x0,0x2,0xfd,0x7b,0xe,
+ 0x0,0xfd,0x1e,0xd,0x0,0x0,0xfd,0x36,0x2,0x90,0xdd,
+ 0x36,0xa6,0x1,0x18,0x0,0xdd,0x36,0xae,0x10,0xdd,0x36,
+ 0xbf,0x1,0xdd,0x72,0xaf,0x2a,0x24,0x1,0xed,0x2d,0xa4,
+ 0xff,0x3a,0x2e,0x1,0x90,0xdd,0x77,0xa7,0xfe,0x4,0xfa,
+ 0xd0,0x2,0xfd,0x7e,0x7f,0xe6,0xf0,0xcb,0x3f,0xcb,0x3f,
+ 0xcb,0x3f,0xcb,0x3f,0x18,0x5,0xfd,0x7e,0x7f,0xe6,0xf,
+ 0xdd,0x77,0xc4,0x21,0x32,0x1,0xc5,0x4f,0xe6,0x7,0xfe,
+ 0x5,0x20,0x17,0x78,0xfe,0x8,0x28,0x4,0xfe,0x4,0x20,
+ 0xe,0xdd,0x36,0xc7,0x1,0x3e,0x8,0x90,0xfd,0x77,0x7f,
+ 0xfd,0x36,0x4b,0x80,0x6,0x0,0xed,0xc6,0x7e,0xdd,0x77,
+ 0xc6,0xc1,0x5,0x20,0x23,0x2a,0x28,0x1,0xfd,0xed,0xf6,
+ 0x80,0x0,0x22,0x28,0x1,0xfd,0x2a,0x28,0x1,0x2a,0x20,
+ 0x1,0xed,0x2d,0xa0,0xff,0xed,0x2a,0x0,0x0,0xfd,0xed,
+ 0xf6,0x0,0x4,0xc,0xc3,0x1f,0x2,0xed,0x2a,0x0,0x0,
+ 0xfd,0xed,0xf6,0x0,0x3,0xed,0x2d,0xa0,0xff,0xe5,0xdd,
+ 0xe1,0xed,0x32,0x0,0x0,0x3a,0x2e,0x1,0xfe,0x8,0x20,
+ 0xf,0x7b,0xfe,0x28,0xca,0x51,0x2,0xfd,0xed,0xf6,0x8,
+ 0x0,0xcb,0x2,0x18,0x1f,0x7b,0xfe,0x24,0xca,0x51,0x2,
+ 0x78,0xfe,0x2,0x20,0x9,0xfd,0xed,0xf6,0x8,0x0,0xcb,
+ 0x2,0x18,0xb,0xfd,0xed,0xf6,0x18,0x0,0xcb,0x2,0xcb,
+ 0x2,0xcb,0x2,0xe5,0xfd,0xe1,0xc3,0x51,0x2,0xcd,0x42,
+ 0x1,0xdd,0x11,0x4,0x80,0x22,0x1,0xdd,0x3e,0x0,0x80,
+ 0x1,0x3e,0x1,0xc9,0xfd,0xed,0x2c,0xa2,0xff,0xcd,0x7f,
+ 0xe,0x18,0x5,0xfd,0xed,0x2c,0xa2,0xff,0xcd,0xd6,0xd,
+ 0x26,0x0,0xc3,0xf3,0x5,0xfd,0xed,0x2c,0xa2,0xff,0xcd,
+ 0x7f,0xe,0x26,0x0,0xc3,0xf3,0x5,0xfd,0xed,0x2c,0xa2,
+ 0xff,0xcd,0x3,0xe,0x26,0x0,0xc3,0xf3,0x5,0xfd,0xed,
+ 0x2c,0xa2,0xff,0xcd,0x20,0xe,0x26,0x0,0xc3,0xf3,0x5,
+ 0xfd,0xed,0x2c,0xa2,0xff,0xfd,0x36,0x2,0x60,0xdd,0x36,
+ 0xae,0x12,0xdd,0x3e,0xc5,0x5,0x1,0x26,0x0,0xc3,0xf3,
+ 0x5,0xfd,0xed,0x2c,0xa2,0xff,0xfd,0x36,0x2,0x75,0xdd,
+ 0x36,0xae,0x0,0xdd,0x3e,0xc5,0x5,0x1,0x26,0x0,0xc3,
+ 0xf3,0x5,0x26,0x0,0xc3,0xf3,0x5,0xfd,0xed,0x2c,0xa2,
+ 0xff,0xdd,0x7e,0xad,0xdd,0x77,0xac,0xdd,0x7e,0xb5,0xe6,
+ 0x10,0x28,0x25,0xed,0x32,0x0,0x0,0xcb,0x5d,0x28,0xa,
+ 0xcb,0x9d,0xfd,0x7b,0xd,0x0,0xcb,0x2f,0x18,0x6,0xfd,
+ 0x7b,0xd,0x0,0xcb,0x27,0x2f,0xe6,0x2,0x20,0x8,0xfd,
+ 0x36,0x2,0x30,0xfd,0x36,0x2,0x4,0xdd,0x7e,0xa8,0xe6,
+ 0x6,0xfe,0x6,0x20,0xe,0xdd,0xcb,0xa8,0x96,0xdd,0xcb,
+ 0xa9,0x4e,0x20,0x4,0xdd,0xcb,0xa3,0xa6,0xdd,0x36,0xae,
+ 0x0,0xdd,0x3e,0xc5,0x5,0x1,0x26,0x0,0xc3,0xf3,0x5,
+ 0xfd,0xed,0x2c,0xa2,0xff,0xdd,0x7e,0xab,0xdd,0x77,0xaa,
+ 0xdd,0x36,0xae,0x0,0xdd,0x3e,0xc5,0x5,0x1,0x26,0x0,
+ 0xc3,0xf3,0x5,0xdd,0xcb,0xa8,0x4e,0x28,0x8,0xdd,0xcb,
+ 0xa8,0xd6,0xdd,0xcb,0xa3,0xe6,0xdd,0x36,0xae,0x0,0xdd,
+ 0x3e,0xc5,0x5,0x1,0x26,0x0,0xc3,0xf3,0x5,0xdd,0x2a,
+ 0x20,0x1,0x21,0xfe,0x0,0xe,0x8,0xed,0x6e,0x3e,0x28,
+ 0xd3,0xe0,0x2a,0x2,0x80,0x1,0xe2,0x0,0xed,0xbf,0x3e,
+ 0xe0,0xd3,0xe1,0x3a,0x6,0x80,0x32,0xc4,0x4,0x21,0xff,
+ 0x0,0xe,0x8,0xed,0x6e,0x26,0x0,0x3a,0x93,0x0,0xfe,
+ 0x1,0xc2,0xf8,0x5,0xd9,0x26,0x0,0xd9,0xc3,0xc,0xd,
+ 0x0,0x0,0x0,0xdd,0xd1,0xc5,0x4,0xf5,0xc5,0xe5,0xdd,
+ 0xe5,0xfd,0xe5,0x3a,0x16,0x80,0xfe,0x1,0x20,0x8,0xcd,
+ 0x42,0x1,0xdd,0x3e,0xc5,0x5,0x1,0x3a,0x93,0x0,0xfe,
+ 0x1,0x28,0x2c,0xdd,0x21,0xe0,0x81,0x18,0x10,0xdd,0xed,
+ 0x2c,0xa0,0xff,0xed,0x2a,0x0,0x0,0xfd,0xed,0xf7,0xe0,
+ 0x81,0x28,0x16,0xdd,0x7e,0xae,0xfe,0x0,0x20,0xe9,0xfd,
+ 0xed,0x2c,0xa2,0xff,0xdd,0x46,0xa9,0xcb,0x68,0x28,0xdd,
+ 0xc3,0x74,0x8,0x21,0xfe,0x0,0xe,0x8,0xed,0x6e,0x2a,
+ 0x2,0x80,0x1,0xe2,0x0,0xed,0xbf,0x3e,0x0,0xd3,0xe1,
+ 0x3e,0xe0,0xd3,0xe1,0x3a,0x93,0x0,0xfe,0x1,0x28,0x3,
+ 0xed,0x7f,0x1,0xdd,0x13,0xa,0x80,0xdd,0x3c,0xc,0x80,
+ 0x3a,0xc5,0x5,0xfe,0x0,0x20,0xe,0x3a,0xc4,0x5,0xfe,
+ 0x0,0x28,0x27,0x3a,0xc4,0x4,0xfe,0x0,0x20,0x20,0xdd,
+ 0x3e,0x1,0xf0,0x1,0xdd,0x3e,0xc4,0x5,0x0,0x3a,0x8,
+ 0x80,0xfe,0x1,0x28,0xa,0xdd,0x3e,0xc,0x80,0x0,0xdd,
+ 0x3e,0x8,0x80,0x1,0xdd,0x3e,0xc5,0x5,0x0,0xf3,0x3a,
+ 0xc4,0x4,0xfe,0x0,0x20,0x6,0x3a,0x6,0x80,0x32,0xc4,
+ 0x4,0xdd,0x3d,0xc4,0x4,0x21,0xff,0x0,0xe,0x8,0xed,
+ 0x6e,0xfd,0xe1,0xdd,0xe1,0xe1,0xc1,0xf1,0xed,0x55,0xc6,
+ 0x5,0xa0,0x3,0x89,0x3,0x93,0x3,0xa0,0x3,0xad,0x3,
+ 0xc7,0x3,0xde,0x3,0xf5,0x3,0xf5,0x3,0xba,0x3,0x31,
+ 0x4,0xfa,0x3,0x56,0x4,0x6f,0x4,0xf5,0x3,0xf5,0x3,
+ 0xf5,0x3,0x1d,0x10,0xf1,0x10,0xf5,0x3,0xf5,0x3,0xbb,
+ 0x11,0x1d,0x10,0x0,0x0,0xfd,0xed,0x2c,0xa2,0xff,0xfd,
+ 0x4c,0xfd,0x5e,0x1,0xcb,0x61,0x20,0x38,0xcb,0x53,0x28,
+ 0x17,0xdd,0x6e,0xac,0xdd,0x7e,0xad,0x95,0x28,0xe,0xe6,
+ 0x3f,0xca,0x29,0x7,0xdd,0x79,0xfd,0x77,0x3,0x2c,0xdd,
+ 0x75,0xac,0xcb,0x43,0x20,0x52,0xdd,0x7e,0xa1,0xdd,0x67,
+ 0xdd,0x7e,0xae,0xfe,0x0,0x28,0xc7,0xfe,0x10,0x28,0xf0,
+ 0x6f,0xfd,0xed,0xf6,0x94,0x5,0xed,0x26,0xe9,0xdd,0x4e,
+ 0xa8,0xdd,0x46,0xa9,0xcb,0x53,0x28,0x25,0xcb,0x71,0xc2,
+ 0xde,0x6,0xcb,0x51,0x20,0x1c,0xdd,0x6e,0xac,0xdd,0x7e,
+ 0xad,0x95,0x28,0x13,0xe6,0x3f,0xca,0x2,0x7,0xdd,0x79,
+ 0xfe,0xa,0xca,0xe5,0x6,0xfd,0x77,0x3,0x2c,0xdd,0x75,
+ 0xac,0xcb,0x43,0x20,0xc,0xcb,0x61,0x20,0x6a,0x18,0xae,
+ 0xdd,0x4e,0xa8,0xdd,0x46,0xa9,0xfd,0x36,0x2,0x40,0xfd,
+ 0x7e,0x3,0xdd,0xa6,0xc3,0xfe,0x0,0xca,0x12,0x8,0xcb,
+ 0x49,0x20,0x34,0x8,0xdd,0x6e,0xaa,0x7d,0x3c,0xdd,0x96,
+ 0xab,0xcb,0x7f,0x28,0x5,0xfe,0xfe,0xf2,0xef,0x8,0x8,
+ 0x26,0x1,0xcb,0x78,0xc2,0x31,0x8,0xed,0xb,0x26,0x0,
+ 0x2c,0xdd,0x75,0xaa,0xdd,0x3e,0xc4,0x5,0x1,0xcb,0x59,
+ 0xca,0xef,0x8,0x8,0xfe,0xc0,0xca,0x98,0x7,0x18,0x23,
+ 0xcb,0x41,0xca,0xe8,0x7,0xcb,0x51,0xc2,0xee,0x7,0xdd,
+ 0xbe,0xb1,0x20,0xbd,0xcb,0xd1,0xdd,0xcb,0xa3,0xe6,0xdd,
+ 0x71,0xa8,0xc3,0xef,0x8,0xdd,0x6e,0xaa,0x7d,0x3c,0xdd,
+ 0x96,0xab,0xcb,0x7f,0xc2,0xef,0x8,0xfe,0x40,0xf2,0xef,
+ 0x8,0xcb,0x79,0xc2,0xc4,0x7,0xcb,0x69,0xca,0xef,0x8,
+ 0xcb,0xa1,0xcb,0xf1,0xdd,0x71,0xa8,0xdd,0xcb,0xb4,0x7e,
+ 0xca,0xef,0x8,0xfd,0x36,0x2,0x80,0xc3,0xef,0x8,0xcb,
+ 0x79,0xc2,0x80,0x7,0x18,0x6b,0xcb,0x50,0xca,0x34,0x6,
+ 0xcb,0x40,0x20,0xc,0xfd,0x36,0x3,0xd,0xcb,0xc0,0xdd,
+ 0x70,0xa9,0xc3,0x3b,0x6,0xcb,0x80,0xdd,0x70,0xa9,0xc3,
+ 0x34,0x6,0xdd,0x7e,0xad,0x95,0xfe,0x40,0x20,0x12,0xcb,
+ 0x58,0xca,0x2d,0x6,0xcb,0x98,0xdd,0x70,0xa9,0xdd,0x3e,
+ 0xc5,0x5,0x1,0xc3,0x2d,0x6,0xfe,0xc0,0xc2,0x2d,0x6,
+ 0xcb,0xd8,0xdd,0x70,0xa9,0xc3,0x2d,0x6,0xdd,0x7e,0xad,
+ 0x95,0xfe,0x40,0x20,0x13,0xdd,0xcb,0xa9,0x5e,0xca,0xe6,
+ 0x5,0xdd,0xcb,0xa9,0x9e,0xdd,0x3e,0xc5,0x5,0x1,0xc3,
+ 0xe6,0x5,0xfe,0xc0,0xc2,0xe6,0x5,0xdd,0xcb,0xa9,0xde,
+ 0xc3,0xe6,0x5,0xdd,0xcb,0xba,0x5e,0x28,0x6,0xdd,0x56,
+ 0xb2,0xfd,0x72,0x3,0xdd,0xcb,0xb4,0x7e,0x28,0x4,0xfd,
+ 0x36,0x2,0x80,0xcb,0xb1,0xcb,0xa9,0xcb,0xa1,0xdd,0x71,
+ 0xa8,0xcb,0x48,0xc2,0x3b,0x6,0xcb,0x51,0xc2,0x3b,0x6,
+ 0xdd,0xcb,0xa3,0xa6,0xc3,0x3b,0x6,0xdd,0xcb,0xba,0x5e,
+ 0x28,0x6,0xdd,0x56,0xb3,0xfd,0x72,0x3,0xcb,0xe9,0xcb,
+ 0xb9,0xcb,0xb1,0xdd,0x71,0xa8,0xc3,0x3b,0x6,0xcb,0x69,
+ 0x20,0xf,0xcb,0xf9,0xcb,0xf1,0xcb,0xe1,0xdd,0xcb,0xa3,
+ 0xe6,0xdd,0x71,0xa8,0x18,0x2,0xcb,0xb1,0xdd,0xcb,0xb4,
+ 0x7e,0xca,0xef,0x8,0xfd,0x36,0x2,0x90,0xcb,0xe1,0xdd,
+ 0xcb,0xa3,0xe6,0xdd,0x71,0xa8,0xc3,0xef,0x8,0xcb,0xb9,
+ 0xcb,0xb1,0xcb,0xa1,0xdd,0x71,0xa8,0xdd,0xcb,0xb4,0x7e,
+ 0x28,0x4,0xfd,0x36,0x2,0x80,0xcb,0x48,0xc2,0xef,0x8,
+ 0xcb,0x51,0xc2,0xef,0x8,0xdd,0xcb,0xa3,0xa6,0xc3,0xef,
+ 0x8,0xdd,0xbe,0xb0,0xc2,0x9c,0x6,0xcb,0x91,0xcb,0x48,
+ 0x20,0xc,0xcb,0x61,0x20,0x8,0xcb,0x71,0x20,0x4,0xdd,
+ 0xcb,0xa3,0xa6,0xdd,0x71,0xa8,0xdd,0xbe,0xb0,0xca,0xef,
+ 0x8,0xdd,0xbe,0xb1,0xca,0xef,0x8,0xc3,0x5e,0x6,0xcb,
+ 0x7b,0xca,0x5a,0x6,0xdd,0xcb,0xc1,0x46,0xc2,0xef,0x8,
+ 0xdd,0xcb,0xc1,0x4e,0xca,0x5a,0x6,0xdd,0xcb,0xb9,0xc6,
+ 0xdd,0x3e,0xc5,0x5,0x1,0xc3,0xef,0x8,0x57,0x7b,0xe6,
+ 0x70,0x7a,0x20,0xe,0xdd,0xcb,0xc1,0x56,0xca,0x78,0x6,
+ 0xfe,0xff,0x28,0x27,0xc3,0x78,0x6,0xdd,0xcb,0xc1,0x5e,
+ 0x28,0x5,0x26,0x0,0xc3,0xef,0x8,0xdd,0xcb,0xc1,0x56,
+ 0x20,0x6,0xdd,0xe,0x0,0xc3,0x7a,0x6,0xdd,0xe,0xff,
+ 0x2c,0xdd,0xe,0x0,0x2c,0xed,0xb,0xc3,0x7a,0x6,0xdd,
+ 0xe,0xff,0x2c,0xdd,0xe,0xff,0xc3,0x7a,0x6,0xed,0x32,
+ 0x0,0x0,0xcb,0x5d,0x28,0xa,0xcb,0x9d,0xfd,0x7b,0xd,
+ 0x0,0xcb,0x2f,0x18,0x6,0xfd,0x7b,0xd,0x0,0xcb,0x27,
+ 0x26,0x0,0x2f,0xcb,0x60,0x20,0x4,0xe6,0x26,0x18,0x2,
+ 0xe6,0x24,0xdd,0xbe,0xb8,0xca,0xee,0x4,0xf5,0xdd,0xae,
+ 0xb8,0xe6,0x4,0x20,0x10,0xf1,0xdd,0x77,0xb8,0xdd,0xcb,
+ 0xb9,0xce,0xdd,0x3e,0xc5,0x5,0x1,0xc3,0xee,0x4,0xdd,
+ 0xcb,0xb5,0x66,0x28,0xea,0xf1,0xf5,0xfd,0x36,0x2,0x10,
+ 0xfd,0x36,0x2,0x30,0xfd,0x36,0x2,0x20,0xcb,0x57,0x28,
+ 0xf,0xfd,0x7e,0x0,0xdd,0x7e,0xb5,0xfd,0x77,0x0,0xfd,
+ 0x36,0x2,0x5,0x18,0xc9,0xfd,0x7e,0x0,0xdd,0x7e,0xb5,
+ 0xe6,0xef,0xfd,0x77,0x0,0xfd,0x36,0x2,0x5,0x18,0xb8,
+ 0xfd,0x5e,0x1,0xc3,0xef,0x5,0xfd,0xed,0x2c,0xa2,0xff,
+ 0xdd,0x7e,0xa7,0xfd,0x77,0x7f,0xe6,0x3,0xfd,0x77,0x68,
+ 0xc9,0xf5,0xc5,0xdd,0x7e,0xc6,0xfd,0x46,0x6c,0xa0,0x47,
+ 0xe,0x0,0xcb,0x78,0x28,0x12,0xcb,0xd1,0xdd,0xcb,0xb5,
+ 0x66,0x28,0x12,0xfd,0x7e,0x9,0xf6,0x2,0xfd,0x77,0x9,
+ 0x18,0x8,0xfd,0x7e,0x9,0xe6,0xfd,0xfd,0x77,0x9,0xcb,
+ 0x68,0x28,0x2,0xcb,0xf1,0xcb,0x60,0x28,0x2,0xcb,0xe9,
+ 0xcb,0x70,0x28,0x2,0xcb,0xc9,0xdd,0x71,0xb8,0xc1,0xf1,
+ 0xc9,0xcd,0xf5,0x8,0xdd,0x7e,0xbf,0xfe,0x1,0x20,0x22,
+ 0xed,0x2c,0xa4,0xff,0xdd,0x7e,0xa7,0xfe,0x4,0xf2,0x69,
+ 0x9,0xfd,0x1c,0x1c,0x0,0xf6,0x8,0xfd,0x77,0x7f,0x18,
+ 0x2d,0xfd,0x1c,0x1d,0x0,0xf6,0x20,0xfd,0x77,0x7f,0x18,
+ 0x22,0xdd,0x7e,0xc5,0xfe,0x1,0x28,0x1b,0xdd,0xcb,0xa9,
+ 0x4e,0x20,0x15,0xdd,0xcb,0xa9,0xc6,0xdd,0x7e,0xc7,0xfe,
+ 0x1,0x28,0x5,0xfd,0x36,0x6,0x92,0xc9,0xfd,0x36,0x6,
+ 0x94,0xc9,0xdd,0x36,0xbf,0x0,0xfd,0x7e,0x5,0xfe,0x0,
+ 0xc0,0xdd,0x7e,0xc5,0xfe,0x1,0xca,0x5c,0xb,0xdd,0x7e,
+ 0xc7,0xfe,0x1,0x20,0xb,0xfd,0x36,0x76,0x0,0xfd,0x36,
+ 0x72,0x42,0xc3,0xd3,0xa,0xdd,0x7e,0xb6,0xe6,0xf,0xcb,
+ 0x27,0x4f,0x6,0x0,0xfd,0x7e,0x40,0xfe,0x42,0x28,0x5,
+ 0x21,0x5e,0x18,0x18,0x3,0x21,0x42,0x18,0xed,0xc6,0x46,
+ 0xfd,0x70,0x72,0x23,0x46,0xfd,0x70,0x76,0xdd,0x7e,0xb6,
+ 0xe6,0xf0,0xcb,0x3f,0xcb,0x3f,0xcb,0x3f,0x4f,0x6,0x0,
+ 0xfd,0x7e,0x40,0xfe,0x42,0x28,0x5,0x21,0x5e,0x18,0x18,
+ 0x3,0x21,0x42,0x18,0xed,0xc6,0x46,0xfd,0x70,0x78,0x23,
+ 0x46,0xfd,0x70,0x7c,0xdd,0x7e,0xbb,0xfd,0x77,0x1a,0xdd,
+ 0x7e,0xbc,0xfd,0x77,0x1b,0xdd,0x7e,0xbd,0xfd,0x77,0x1c,
+ 0xdd,0x7e,0xbe,0xfd,0x77,0x1d,0xdd,0x36,0xb9,0x0,0xdd,
+ 0x7e,0xb4,0xe6,0x3,0x47,0xdd,0x7e,0xb4,0xe6,0x14,0xfe,
+ 0x10,0x28,0xc,0xfe,0x4,0x28,0x4,0x3e,0x40,0x18,0x6,
+ 0x3e,0xc0,0x18,0x2,0x3e,0x0,0xb0,0x47,0xdd,0x7e,0xba,
+ 0xe6,0x80,0x20,0x4,0x78,0xf6,0x10,0x47,0xdd,0x7e,0xb5,
+ 0xe6,0xf,0xfe,0x7,0x78,0x20,0x4,0xf6,0x0,0x18,0x2,
+ 0xf6,0x8,0xfd,0x77,0x8,0xdd,0x7e,0xb5,0xe6,0x10,0x28,
+ 0x4,0x6,0x2,0x18,0x2,0x6,0x0,0xdd,0x7e,0xb5,0xe6,
+ 0x80,0x28,0x4,0x3e,0x10,0xb0,0x47,0xdd,0x7e,0xba,0xe6,
+ 0x2,0x28,0x11,0xdd,0x7e,0xba,0xe6,0x1,0x28,0x6,0x3e,
+ 0xc0,0xb0,0x47,0x18,0x4,0x3e,0x40,0xb0,0x47,0xfd,0x70,
+ 0x9,0xdd,0x7e,0xba,0xe6,0x2,0x28,0x6,0xfd,0x36,0xa,
+ 0x36,0x18,0x4,0xfd,0x36,0xa,0x6,0xdd,0xcb,0xc0,0x5e,
+ 0x28,0x4,0x6,0x2,0x18,0xc,0xdd,0xcb,0xc0,0x56,0x28,
+ 0x4,0x6,0x4,0x18,0x2,0x6,0x3,0xdd,0xcb,0xc0,0x46,
+ 0x28,0x4,0x3e,0x18,0x18,0xc,0xdd,0xcb,0xc0,0x4e,0x28,
+ 0x4,0x3e,0x0,0x18,0x2,0x3e,0x8,0xb0,0xfd,0x77,0x1e,
+ 0xdd,0x7e,0xba,0xe6,0x4,0x28,0x16,0xdd,0x7e,0xc7,0xfe,
+ 0x1,0x20,0x7,0xfd,0x7e,0x40,0xfe,0x42,0x28,0x8,0x6,
+ 0x2,0xdd,0xcb,0xa9,0x96,0x18,0x2,0x6,0x0,0xdd,0x7e,
+ 0xc2,0xfe,0xff,0x28,0x4,0x3e,0x80,0xb0,0x47,0xfd,0x70,
+ 0x1f,0xdd,0x7e,0xba,0xdd,0xcb,0xb4,0x7e,0x20,0x6,0xdd,
+ 0xcb,0xba,0x76,0x28,0x2,0xf6,0x8,0x4f,0xdd,0xae,0xa8,
+ 0xe6,0x9b,0x47,0xdd,0x7e,0xa8,0xa8,0xcb,0x5f,0x28,0x2,
+ 0xe6,0xf,0x47,0xdd,0x70,0xa8,0x79,0xe6,0xfb,0xdd,0xae,
+ 0xa9,0xe6,0xa4,0x47,0xdd,0x7e,0xa9,0xa8,0xdd,0x77,0xa9,
+ 0xdd,0x7e,0xc7,0xfe,0x1,0x20,0x12,0xfd,0x7e,0x40,0xfe,
+ 0x42,0x20,0xb,0xdd,0x7e,0xba,0xe6,0x4,0x28,0x4,0xdd,
+ 0xcb,0xa9,0xd6,0xfd,0x36,0x21,0x2,0xfd,0x36,0x5,0x4e,
+ 0xdd,0x36,0xc5,0x1,0xc9,0xdd,0x36,0xc5,0x0,0xdd,0xcb,
+ 0xa8,0x86,0xdd,0x7e,0xc7,0xfe,0x1,0xca,0x17,0xc,0xfd,
+ 0x36,0x5,0x1a,0xdd,0xcb,0xb7,0x46,0x20,0x6,0xdd,0xcb,
+ 0xb4,0x7e,0x28,0x13,0xdd,0x7e,0xc4,0xe6,0x8,0x20,0x6,
+ 0xfd,0x36,0x6c,0x1,0x18,0x17,0xfd,0x36,0x6d,0x2,0x18,
+ 0x11,0xdd,0x7e,0xc4,0xe6,0x8,0x20,0x6,0xfd,0x36,0x6c,
+ 0x0,0x18,0x4,0xfd,0x36,0x6d,0x0,0xdd,0xcb,0xb7,0x4e,
+ 0x20,0x6,0xdd,0xcb,0xba,0x76,0x28,0x13,0xdd,0x7e,0xc4,
+ 0xe6,0x8,0x20,0x6,0xfd,0x36,0x6d,0x2,0x18,0x17,0xfd,
+ 0x36,0x6c,0x1,0x18,0x11,0xdd,0x7e,0xc4,0xe6,0x8,0x20,
+ 0x6,0xfd,0x36,0x6d,0x0,0x18,0x4,0xfd,0x36,0x6c,0x0,
+ 0xdd,0xcb,0xba,0x6e,0x28,0x15,0xcd,0x6,0x9,0xdd,0x7e,
+ 0xb5,0xe6,0x10,0x28,0x4,0x3e,0xb0,0x18,0x2,0x3e,0xf0,
+ 0xdd,0xa6,0xc6,0x18,0x6,0x3e,0x0,0xdd,0x36,0xb8,0x24,
+ 0xfd,0x77,0x16,0xdd,0xcb,0xba,0x76,0x28,0xa,0xdd,0xcb,
+ 0xc4,0x5e,0x20,0x4,0xf6,0x8,0x18,0xe,0xdd,0xcb,0xb4,
+ 0x7e,0x28,0x8,0xdd,0xcb,0xc4,0x5e,0x28,0x2,0xf6,0x8,
+ 0xfd,0x77,0x15,0x18,0xc,0xfd,0x36,0x15,0x0,0xfd,0x36,
+ 0x16,0x0,0xfd,0x36,0x5,0x18,0xfd,0x36,0x6,0x90,0xdd,
+ 0x36,0xae,0x0,0xdd,0x3e,0xc5,0x5,0x1,0xc9,0xcd,0xf5,
+ 0x8,0xfd,0x7e,0x6c,0xe6,0x80,0x28,0xa,0xdd,0x36,0xae,
+ 0x0,0xdd,0x3e,0xc5,0x5,0x1,0xc9,0xdd,0x36,0xae,0x6,
+ 0xc9,0xcd,0x48,0x9,0x18,0x5,0xfd,0xed,0x2c,0xa2,0xff,
+ 0xcd,0x31,0xc,0x26,0x0,0xc3,0xc,0xd,0xcd,0x48,0x9,
+ 0x26,0x0,0xc3,0xc,0xd,0xcd,0xea,0x1c,0x26,0x0,0xc3,
+ 0xc,0xd,0xcd,0xea,0x1c,0x26,0x0,0xc3,0xc,0xd,0x26,
+ 0x0,0xc3,0xc,0xd,0xcd,0xf5,0x8,0xfd,0x7e,0x5,0xfe,
+ 0x0,0x28,0x5,0x26,0x0,0xc3,0xc,0xd,0xdd,0x7e,0xad,
+ 0xdd,0x77,0xac,0xfd,0x36,0x5,0x82,0xcd,0xf5,0x8,0xdd,
+ 0x7e,0xc7,0xfe,0x1,0x28,0x8,0xfd,0x7e,0xb,0xe6,0xfb,
+ 0xfd,0x77,0xb,0xdd,0x36,0xae,0x0,0xdd,0x3e,0xc5,0x5,
+ 0x1,0x26,0x0,0x18,0x5b,0xfd,0xed,0x2c,0xa2,0xff,0xdd,
+ 0x7e,0xab,0xdd,0x77,0xaa,0xdd,0x36,0xae,0x0,0xdd,0x3e,
+ 0xc5,0x5,0x1,0x26,0x0,0x18,0x43,0xcd,0xf5,0x8,0xfd,
+ 0x7e,0xb,0xf6,0x4,0xfd,0x77,0xb,0xdd,0x36,0xae,0x0,
+ 0xdd,0x3e,0xc5,0x5,0x1,0x26,0x0,0x18,0x2b,0xcd,0x72,
+ 0x1b,0x26,0x0,0x18,0x24,0x74,0xc,0x5c,0xc,0x4a,0xc,
+ 0x4f,0xc,0x5c,0xc,0x64,0xc,0x2d,0x1c,0x89,0x1c,0x74,
+ 0xc,0x74,0xc,0x6c,0xc,0x92,0xc,0x79,0xc,0xb1,0xc,
+ 0xc9,0xc,0xe1,0xc,0x74,0xc,0x74,0xc,0xed,0x7f,0x17,
+ 0xdd,0x7e,0xa1,0xdd,0x67,0xdd,0x7e,0xae,0xfe,0x0,0xf3,
+ 0xc2,0xa9,0xd,0xdd,0x46,0xa8,0xcb,0x40,0xca,0xb6,0xd,
+ 0xcb,0x60,0x28,0xe3,0xcd,0xf5,0x8,0xcb,0x78,0x28,0x16,
+ 0xfd,0x7e,0x5,0xfe,0x0,0x20,0xd5,0xfd,0x36,0x5,0x24,
+ 0xcb,0xe8,0xcb,0xb8,0xcb,0xb0,0xdd,0x70,0xa8,0x18,0xc6,
+ 0xdd,0x6e,0xaa,0x7d,0xdd,0x96,0xab,0xcb,0x7f,0x20,0xbb,
+ 0xfe,0x40,0xf2,0xc,0xd,0xdd,0xcb,0xba,0x5e,0x28,0xb,
+ 0xfd,0x7e,0x5,0xfe,0x0,0x20,0xa9,0xfd,0x36,0x5,0x23,
+ 0xdd,0xcb,0xb4,0x7e,0x28,0x15,0xdd,0x7e,0xc4,0xe6,0x8,
+ 0x20,0x6,0xfd,0x36,0x6c,0x1,0x18,0x8,0xfd,0x7e,0x6,
+ 0xf6,0x10,0xfd,0x77,0x6,0xdd,0xcb,0xba,0x76,0x28,0x15,
+ 0xdd,0x7e,0xc4,0xe6,0x8,0x20,0xa,0xfd,0x7e,0x6,0xf6,
+ 0x10,0xfd,0x77,0x6,0x18,0x4,0xfd,0x36,0x6c,0x1,0xcb,
+ 0xb0,0xcb,0xa8,0xcb,0xa0,0xdd,0x70,0xa8,0xc3,0xc,0xd,
+ 0xfe,0x10,0xca,0xc,0xd,0x6f,0xfd,0xed,0x3c,0xe8,0xc,
+ 0xfd,0xe9,0xdd,0x6e,0xac,0xdd,0x7e,0xad,0x95,0xca,0x25,
+ 0xd,0xdd,0xcb,0xa8,0xc6,0xcd,0xf5,0x8,0xfd,0x7e,0x6,
+ 0xf6,0x4,0xfd,0x77,0x6,0xdd,0x36,0xc9,0x1,0xc3,0x25,
+ 0xd,0xed,0x32,0x0,0x0,0xcb,0x5d,0x28,0xb,0xcb,0x9d,
+ 0xfd,0x7b,0xd,0x0,0x2f,0xe6,0x8,0x18,0x7,0xfd,0x7b,
+ 0xd,0x0,0x2f,0xe6,0x2,0xfe,0x0,0x28,0xa,0xdd,0x36,
+ 0xae,0x0,0xdd,0x3e,0xc5,0x5,0x1,0xc9,0xdd,0x36,0xae,
+ 0x6,0xc9,0x26,0x0,0xdd,0x7e,0xac,0xdd,0x96,0xad,0x28,
+ 0x4,0xf1,0xc3,0xc6,0x5,0xdd,0x7e,0xbf,0xfe,0x1,0x28,
+ 0x8,0xfd,0x7e,0x1,0xcb,0x5f,0xc8,0x18,0x10,0xdd,0x36,
+ 0xaa,0x0,0xdd,0x36,0xab,0x0,0xdd,0x36,0xac,0x0,0xdd,
+ 0x36,0xad,0x0,0xfd,0xed,0x2c,0xa2,0xff,0xdd,0xcb,0xb7,
+ 0x46,0x20,0x4,0xfd,0x36,0x2,0x90,0xfd,0x36,0x2,0x30,
+ 0xfd,0x36,0x2,0x20,0xdd,0x36,0xbf,0x1,0xdd,0xcb,0xb7,
+ 0x4e,0x20,0x24,0xfd,0xe5,0xed,0x32,0x0,0x0,0x7d,0xe6,
+ 0x80,0x6f,0xfd,0xed,0x2c,0xa4,0xff,0xfd,0x7e,0x4,0x47,
+ 0xdd,0x7e,0xaf,0x2f,0xa0,0xfd,0x77,0x4,0xe5,0xfd,0xe1,
+ 0x2f,0xfd,0x77,0x40,0xfd,0xe1,0xdd,0x36,0xae,0x10,0xdd,
+ 0x3e,0xc5,0x5,0x1,0xc9,0xdd,0x7e,0xbf,0xfe,0x1,0x28,
+ 0x6,0xfd,0x7e,0x1,0xcb,0x5f,0xc8,0xdd,0x36,0xbf,0x0,
+ 0xfd,0x36,0x2,0x18,0xdd,0x7e,0xb4,0xe6,0x7f,0xfd,0x77,
+ 0x0,0xdd,0xcb,0xb4,0x7e,0x20,0x12,0xdd,0xcb,0xb7,0x46,
+ 0x20,0x6,0xfd,0x36,0x2,0x90,0x18,0xa,0xfd,0x36,0x2,
+ 0x80,0x18,0x4,0xfd,0x36,0x2,0x80,0xdd,0x7e,0xb5,0xfd,
+ 0x77,0x0,0xcb,0x67,0x20,0x6,0xdd,0xcb,0xa9,0xa6,0x18,
+ 0x4,0xdd,0xcb,0xa9,0xe6,0xfd,0xe5,0xed,0x32,0x0,0x0,
+ 0x7d,0xe6,0x80,0x6f,0xfd,0xed,0x2c,0xa4,0xff,0xfd,0x7e,
+ 0x4,0xdd,0xcb,0xb7,0x4e,0x28,0x5,0xdd,0xb6,0xaf,0x18,
+ 0x6,0x47,0xdd,0x7e,0xaf,0x2f,0xa0,0xfd,0x77,0x4,0xe5,
+ 0xfd,0xe1,0x2f,0xfd,0x77,0x40,0xfd,0xe1,0xdd,0x7e,0xb6,
+ 0xfd,0x77,0x1,0xdd,0x36,0xb9,0x0,0xdd,0x7e,0xbb,0xdd,
+ 0x77,0xb0,0xdd,0x7e,0xbc,0xdd,0x77,0xb1,0xdd,0x7e,0xbd,
+ 0xdd,0x77,0xb2,0xdd,0x7e,0xbe,0xdd,0x77,0xb3,0xdd,0x36,
+ 0xb9,0x0,0xdd,0x7e,0xba,0xdd,0xcb,0xb4,0x7e,0x28,0x2,
+ 0xf6,0x8,0x4f,0xdd,0xae,0xa8,0xe6,0xdb,0x47,0xdd,0x7e,
+ 0xa8,0xa8,0xcb,0x48,0x28,0x2,0xcb,0x97,0xcb,0x5f,0x28,
+ 0x2,0xe6,0xf,0x47,0x79,0xe6,0x54,0x20,0xa,0xdd,0xcb,
+ 0xa9,0x8e,0xdd,0xcb,0xa3,0xa6,0x18,0x8,0xdd,0xcb,0xa3,
+ 0xe6,0xdd,0xcb,0xa9,0xce,0xdd,0x70,0xa8,0x79,0xdd,0xae,
+ 0xa9,0xe6,0xa4,0x47,0xdd,0x7e,0xa9,0xa8,0xcb,0x50,0x28,
+ 0x2,0xcb,0x87,0xdd,0x77,0xa9,0xcb,0x6f,0x20,0x6,0xdd,
+ 0x36,0xb8,0x24,0x18,0x3b,0xed,0x32,0x0,0x0,0xcb,0x5d,
+ 0x28,0xa,0xcb,0x9d,0xfd,0x7b,0xd,0x0,0xcb,0x2f,0x18,
+ 0x6,0xfd,0x7b,0xd,0x0,0xcb,0x27,0x2f,0xdd,0xcb,0xa9,
+ 0x66,0x20,0x4,0xe6,0x26,0x18,0x15,0xe6,0x24,0xdd,0x77,
+ 0xb8,0xcb,0x57,0x28,0x2,0x18,0xd,0xdd,0x7e,0xb5,0xe6,
+ 0xef,0xfd,0x77,0x0,0x18,0x3,0xdd,0x77,0xb8,0xdd,0x7e,
+ 0xc0,0xdd,0x77,0xc1,0xdd,0x7e,0xc2,0xdd,0x77,0xc3,0xfd,
+ 0x36,0x2,0x5,0xdd,0x36,0xae,0x0,0xdd,0x3e,0xc5,0x5,
+ 0x1,0xc9,0x45,0x6e,0x64,0x20,0x6f,0x66,0x20,0x74,0x61,
+ 0x20,0x63,0x6f,0x64,0x65,0x0,0x0,0xdd,0xd1,0xdf,0xf,
+ 0xe5,0xdd,0xe5,0xc5,0xdd,0x2a,0x2a,0x1,0xe,0x15,0xed,
+ 0xb7,0x21,0x0,0x0,0xed,0xbf,0xdd,0x36,0xae,0x2a,0xc1,
+ 0xdd,0xe1,0xe1,0xed,0x55,0xdd,0xd1,0xdf,0xf,0xe5,0xdd,
+ 0xe5,0xc5,0xdd,0x2a,0x2c,0x1,0xe,0x1d,0x21,0x0,0x0,
+ 0xed,0xbf,0xdd,0x36,0xae,0x2a,0xc1,0xdd,0xe1,0xe1,0xed,
+ 0x55,0xfd,0xed,0x2c,0xa2,0xff,0xdd,0x7e,0xb2,0xe6,0xc,
+ 0x20,0x25,0xdd,0x7e,0xb2,0xe6,0x10,0x28,0x1e,0xfd,0x36,
+ 0x0,0xf,0xfd,0x36,0x0,0x1,0xfd,0x36,0x0,0x7,0xfd,
+ 0x36,0x0,0x3,0xdd,0x7e,0xb3,0xf6,0x9,0xfd,0x36,0x0,
+ 0x5,0xfd,0x77,0x0,0x18,0xc,0xdd,0x7e,0xb3,0xf6,0x8,
+ 0xfd,0x36,0x0,0x5,0xfd,0x77,0x0,0xed,0x32,0x2,0x0,
+ 0x7c,0xf6,0xf0,0x67,0xdd,0x7e,0xa7,0xfe,0x1,0x20,0x44,
+ 0xe,0x10,0xed,0xbf,0x21,0xf,0x80,0xe,0x11,0xed,0xbf,
+ 0xed,0x2a,0x0,0x0,0x7c,0xf6,0xf0,0x67,0xe,0x12,0xed,
+ 0xbf,0xdd,0x7c,0xe6,0x7f,0xf6,0xf,0x6f,0x26,0x0,0xe,
+ 0x13,0xed,0xbf,0xed,0x2c,0xaa,0xff,0xe,0x14,0xed,0xbf,
+ 0x21,0x84,0x88,0xe,0x15,0xed,0xbf,0xfd,0x36,0x0,0x1,
+ 0xfd,0x36,0x0,0xc0,0x26,0x0,0xdd,0x36,0xae,0x28,0xc3,
+ 0xf3,0x5,0xe,0x18,0xed,0xbf,0x21,0xf,0x80,0xe,0x19,
+ 0xed,0xbf,0xed,0x2a,0x0,0x0,0x7c,0xf6,0xf0,0x67,0xe,
+ 0x1a,0xed,0xbf,0xdd,0x7c,0xe6,0x7f,0xf6,0xf,0x6f,0x26,
+ 0x0,0xe,0x1b,0xed,0xbf,0xed,0x2c,0xaa,0xff,0xe,0x1c,
+ 0xed,0xbf,0x21,0x84,0x88,0xe,0x1d,0xed,0xbf,0xfd,0x36,
+ 0x0,0x1,0xfd,0x36,0x0,0xc0,0x26,0x0,0xdd,0x36,0xae,
+ 0x28,0xc3,0xf3,0x5,0xfd,0xed,0x2c,0xa2,0xff,0xdd,0x7e,
+ 0xb2,0xe6,0xc,0x20,0x15,0xdd,0x7e,0xb2,0xe6,0x10,0x28,
+ 0xe,0xdd,0x7e,0xb1,0xf6,0x11,0xfd,0x36,0x0,0x3,0xfd,
+ 0x77,0x0,0x18,0xc,0xdd,0x7e,0xb1,0xf6,0x1,0xfd,0x36,
+ 0x0,0x3,0xfd,0x77,0x0,0xed,0x32,0x2,0x0,0x7c,0xf6,
+ 0xf0,0x67,0xdd,0x7e,0xa7,0xfe,0x1,0x20,0x47,0xe,0x12,
+ 0xed,0xbf,0x21,0xf,0x80,0xe,0x13,0xed,0xbf,0xed,0x2a,
+ 0x0,0xc,0x7c,0xf6,0xf0,0x67,0xe,0x10,0xed,0xbf,0xed,
+ 0x2a,0x0,0xc,0x7c,0xe6,0x7f,0xf6,0xf,0x6f,0x26,0x0,
+ 0xe,0x11,0xed,0xbf,0xed,0x2c,0xaa,0xff,0xe,0x14,0xed,
+ 0xbf,0x21,0x80,0xa0,0xe,0x15,0xed,0xbf,0xfd,0x36,0x0,
+ 0x1,0xfd,0x36,0x0,0xe0,0x26,0x0,0xdd,0x36,0xae,0x28,
+ 0xc3,0xf3,0x5,0xe,0x1a,0xed,0xbf,0x21,0xf,0x80,0xe,
+ 0x1b,0xed,0xbf,0xed,0x2a,0x0,0xc,0x7c,0xf6,0xf0,0x67,
+ 0xe,0x18,0xed,0xbf,0xed,0x2a,0x0,0xc,0x7c,0xe6,0x7f,
+ 0xf6,0xf,0x6f,0x26,0x0,0xe,0x19,0xed,0xbf,0xed,0x2c,
+ 0xaa,0xff,0xe,0x1c,0xed,0xbf,0x21,0x80,0xa0,0xe,0x1d,
+ 0xed,0xbf,0xfd,0x36,0x0,0x1,0xfd,0x36,0x0,0xe0,0x26,
+ 0x0,0xdd,0x36,0xae,0x28,0xc3,0xf3,0x5,0xfd,0xed,0x2c,
+ 0xa2,0xff,0xdd,0x7e,0xb1,0xfd,0x36,0x0,0x3,0xfd,0x77,
+ 0x0,0xdd,0x7e,0xb2,0xfd,0x36,0x0,0x4,0xfd,0x77,0x0,
+ 0xdd,0x7e,0xb3,0xfd,0x36,0x0,0x5,0xfd,0x77,0x0,0xdd,
+ 0x7e,0xb4,0xfd,0x36,0x0,0x6,0xfd,0x77,0x0,0xdd,0x7e,
+ 0xb5,0xfd,0x36,0x0,0x7,0xfd,0x77,0x0,0xdd,0x7e,0xb8,
+ 0xfd,0x36,0x0,0xa,0xfd,0x77,0x0,0xdd,0x7e,0xba,0xfd,
+ 0x36,0x0,0xc,0xfd,0x77,0x0,0xdd,0x7e,0xbb,0xfd,0x36,
+ 0x0,0xd,0xfd,0x77,0x0,0xdd,0x36,0xae,0x2a,0xdd,0x3e,
+ 0xc5,0x5,0x1,0x26,0x0,0xc3,0xf3,0x5,0x8,0x0,0x18,
+ 0x0,0x28,0x0,0x38,0x0,0x48,0x0,0x58,0x0,0x68,0x0,
+ 0x8,0x80,0x8,0x0,0x18,0x0,0x28,0x0,0x38,0x0,0x48,
+ 0x0,0x58,0x0,0x68,0x0,0x78,0x0,0x8,0x0,0x18,0x0,
+ 0x28,0x0,0x38,0x0,0x48,0x0,0x58,0x0,0x68,0x0,0x8,
+ 0x80,0x8,0x0,0x18,0x0,0x28,0x0,0x38,0x0,0x48,0x0,
+ 0x58,0x0,0x68,0x0,0x78,0x0,0x7a,0x0,0x6a,0x0,0xfa,
+ 0x0,0xaa,0x0,0xba,0x0,0xca,0x0,0x8,0x80,0x8,0x80,
+ 0x8,0x0,0x18,0x0,0x28,0x0,0x38,0x0,0x48,0x0,0x58,
+ 0x0,0x68,0x0,0x8,0x1,0x7a,0x0,0x6a,0x0,0xfa,0x0,
+ 0xaa,0x0,0xba,0x0,0xca,0x0,0x8,0x80,0x8,0x80,0x8,
+ 0x0,0x18,0x0,0x28,0x0,0x38,0x0,0x48,0x0,0x58,0x0,
+ 0x68,0x0,0x8,0x1,0x6a,0x0,0x7a,0x0,0xfa,0x0,0x9a,
+ 0x0,0xaa,0x0,0xba,0x0,0x8,0x80,0x8,0x80,0x8,0x0,
+ 0x18,0x0,0x28,0x0,0x38,0x0,0x48,0x0,0x58,0x0,0x68,
+ 0x0,0x8,0x1,0x6a,0x0,0x7a,0x0,0xfa,0x0,0x9a,0x0,
+ 0xaa,0x0,0xba,0x0,0x8,0x80,0x8,0x80,0x8,0x0,0x18,
+ 0x0,0x28,0x0,0x38,0x0,0x48,0x0,0x58,0x0,0x68,0x0,
+ 0x8,0x1,0x8a,0x0,0x9a,0x0,0xfa,0x0,0xba,0x0,0xca,
+ 0x0,0xda,0x0,0x8,0x80,0x8,0x80,0x8,0x0,0x18,0x0,
+ 0x28,0x0,0x38,0x0,0x48,0x0,0x58,0x0,0x68,0x0,0x8,
+ 0x1,0x8a,0x0,0x9a,0x0,0xfa,0x0,0xba,0x0,0xca,0x0,
+ 0xda,0x0,0x8,0x80,0x8,0x80,0x8,0x0,0x18,0x0,0x28,
+ 0x0,0x38,0x0,0x48,0x0,0x58,0x0,0x68,0x0,0x8,0x1,
+ 0x3a,0x41,0x0,0xfe,0x0,0x20,0xf9,0x3a,0x0,0x80,0x2f,
+ 0x47,0x32,0x0,0x80,0x3a,0x0,0x80,0xb8,0x28,0x7,0xdd,
+ 0x3e,0x1,0x0,0x20,0x18,0x5,0xdd,0x3e,0x1,0x0,0x40,
+ 0x3a,0x42,0x0,0xfe,0x1,0x20,0x6,0xdd,0x11,0x1c,0x13,
+ 0x8,0x40,0x2a,0x43,0x0,0xe,0xff,0xed,0x6e,0x2a,0x45,
+ 0x0,0xe,0x2,0xed,0x6e,0x21,0x60,0x0,0xe,0x12,0xed,
+ 0x6e,0x21,0x2,0x0,0xe,0x0,0xed,0x6e,0x21,0xff,0x0,
+ 0xe,0x8,0xed,0x6e,0x21,0x0,0x0,0xe,0x16,0xed,0x6e,
+ 0x3e,0x3f,0xd3,0xe8,0xe,0x1f,0x21,0x0,0x0,0xed,0xbf,
+ 0xed,0x4e,0x3e,0x0,0xe,0xf5,0xdd,0x21,0x1e,0x12,0xed,
+ 0x2c,0x0,0x0,0xd3,0xf1,0xed,0xbf,0x3c,0xdd,0x23,0xdd,
+ 0x23,0xfe,0x20,0x20,0xef,0x21,0x0,0x8,0xe,0xf0,0xed,
+ 0xbf,0x0,0x0,0x0,0xdd,0x21,0x8c,0x0,0xfd,0x21,0x0,
+ 0x70,0x21,0x80,0x0,0xe,0x0,0xfd,0xe5,0x6,0x4,0xfd,
+ 0x7e,0xd,0xe6,0xa0,0xfe,0xa0,0x20,0x44,0xe5,0xed,0x32,
+ 0x0,0x0,0xfd,0xed,0xf6,0x10,0x0,0xe5,0xfd,0xe1,0xe1,
+ 0x10,0xe7,0xfd,0xe1,0xfd,0x7e,0x1,0xfe,0xff,0xca,0x5d,
+ 0x14,0xdd,0x3e,0x92,0x0,0x1,0x3a,0x93,0x0,0xfe,0x1,
+ 0xca,0xa5,0x14,0xfd,0x7e,0x40,0xe6,0x1,0x20,0xb,0xdd,
+ 0x36,0x0,0x8,0xfd,0xed,0xf6,0x0,0x19,0x18,0x4d,0xdd,
+ 0x36,0x0,0x4,0xfd,0xed,0xf6,0x0,0xd,0x18,0x42,0xfd,
+ 0xe1,0xfd,0x36,0x7f,0x8,0xdd,0x3e,0x93,0x0,0x1,0x3a,
+ 0x92,0x0,0xfe,0x1,0xca,0xa5,0x14,0xcd,0x4d,0x15,0xfd,
+ 0x36,0x7f,0x10,0xfd,0x7e,0x7f,0xe6,0xf0,0xfe,0xf0,0x20,
+ 0xb,0xdd,0x36,0x0,0x24,0xfd,0xed,0xf6,0x0,0xd,0x18,
+ 0x14,0xfd,0x36,0x7f,0x34,0xcd,0x4d,0x15,0xfd,0x36,0x7f,
+ 0x40,0xdd,0x36,0x0,0x28,0xfd,0xed,0xf6,0x0,0x19,0xdd,
+ 0x23,0xe5,0xed,0x32,0x0,0x0,0xfd,0xed,0xf6,0x80,0x0,
+ 0xe5,0xfd,0xe1,0xe1,0xc,0x79,0xfe,0x4,0xc2,0xb3,0x13,
+ 0x79,0xfe,0x0,0x28,0x43,0xe5,0x21,0xd1,0xf,0xfd,0xed,
+ 0xf7,0x0,0x10,0xe1,0xf2,0x76,0x14,0x3a,0x91,0x0,0xfe,
+ 0x1,0x20,0x5,0xdd,0x3e,0x94,0x0,0x1,0x3a,0x1,0x0,
+ 0xfe,0x40,0x28,0x39,0x22,0x95,0x0,0x21,0x0,0x80,0x3a,
+ 0x94,0x0,0xfe,0x1,0x20,0x7,0xfd,0xed,0xfe,0x0,0x20,
+ 0x18,0x5,0xfd,0xed,0xfe,0x0,0x10,0xdd,0xed,0xde,0x95,
+ 0x0,0xfa,0xb3,0x14,0x18,0x16,0xdd,0x3e,0x0,0x0,0xff,
+ 0x18,0xe,0xdd,0x3e,0x0,0x0,0x2,0x18,0x7,0xdd,0x3e,
+ 0x0,0x0,0x3,0x18,0x0,0x76,0x21,0x0,0x0,0xe,0xf0,
+ 0xed,0xbf,0x0,0x0,0x0,0x1,0xc1,0x1d,0x21,0x0,0x0,
+ 0x3a,0x1,0x0,0xfe,0x20,0x20,0x14,0x3a,0x94,0x0,0xfe,
+ 0x1,0x20,0x5,0x11,0x0,0x60,0x18,0xb,0x1,0xd1,0xf,
+ 0x11,0x0,0x70,0x18,0x3,0x11,0x0,0x80,0xed,0xb0,0x3a,
+ 0x1,0x0,0xfe,0x20,0x20,0x12,0x3a,0x94,0x0,0xfe,0x1,
+ 0x28,0xb,0x1,0xc1,0xd,0x11,0x0,0x60,0x21,0x0,0x10,
+ 0xed,0xb0,0x3a,0x1,0x0,0xfe,0x20,0x20,0x5,0x21,0x70,
+ 0x0,0x18,0x3,0x21,0x80,0x0,0xe,0x6,0xed,0x6e,0x3a,
+ 0x1,0x0,0xfe,0x20,0x20,0x13,0x3a,0x94,0x0,0xfe,0x1,
+ 0x20,0x6,0xdd,0x21,0x9e,0x12,0x18,0xa,0xdd,0x21,0x5e,
+ 0x12,0x18,0x4,0xdd,0x21,0xde,0x12,0x3e,0x0,0xe,0xf5,
+ 0xed,0x2c,0x0,0x0,0xd3,0xf1,0xed,0xbf,0x3c,0xdd,0x23,
+ 0xdd,0x23,0xfe,0x20,0x20,0xef,0xc3,0xc7,0x0,0xf5,0xc5,
+ 0xe5,0xfd,0x36,0x66,0x1,0xfd,0x36,0x68,0x3,0xfd,0x36,
+ 0x74,0x0,0xfd,0x36,0x68,0x2,0xfd,0x36,0x74,0x0,0xfd,
+ 0x36,0x68,0x1,0xfd,0x36,0x74,0x0,0xfd,0x36,0x68,0x0,
+ 0xfd,0x36,0x74,0x0,0xfd,0x36,0x68,0x3,0xfd,0x36,0x7a,
+ 0x0,0xfd,0x36,0x68,0x2,0xfd,0x36,0x7a,0x0,0xfd,0x36,
+ 0x68,0x1,0xfd,0x36,0x7a,0x0,0xfd,0x36,0x68,0x0,0xfd,
+ 0x36,0x7a,0x0,0xfd,0x36,0x68,0x4,0xfd,0x36,0x6d,0xa8,
+ 0xfd,0x36,0x6e,0x0,0xfd,0x36,0x6f,0x0,0xfd,0x36,0x6c,
+ 0x1,0xfd,0x36,0x66,0x3,0xfd,0x36,0x66,0x3,0xfd,0x36,
+ 0x66,0x3,0xfd,0x36,0x68,0x4,0xfd,0x36,0x6d,0xa8,0xfd,
+ 0x36,0x6e,0x20,0xfd,0x36,0x6f,0x0,0xfd,0x36,0x66,0x3,
+ 0xfd,0x36,0x66,0x3,0xfd,0x36,0x66,0x3,0xfd,0x36,0x6c,
+ 0x0,0x6,0xf,0xfd,0x36,0x66,0x3,0x10,0xfa,0xfd,0x36,
+ 0x68,0x4,0xfd,0x36,0x6d,0x0,0xfd,0x36,0x6e,0x20,0xfd,
+ 0x36,0x6f,0x3,0xfd,0x36,0x6c,0x1,0xfd,0x36,0x66,0x3,
+ 0xfd,0x36,0x66,0x3,0xfd,0x36,0x66,0x3,0xfd,0x36,0x66,
+ 0x3,0xfd,0x36,0x6c,0x0,0xfd,0x36,0x66,0x0,0xfd,0x36,
+ 0x68,0x0,0x21,0xff,0x7f,0x2b,0xfd,0xed,0xf7,0x0,0x0,
+ 0x20,0xf8,0xfd,0x36,0x40,0x0,0xfd,0x36,0x5,0x81,0x21,
+ 0xff,0x7f,0xfd,0x7e,0x40,0xfe,0x0,0x28,0xf9,0xfd,0x36,
+ 0x4b,0x0,0xfd,0x36,0x7e,0xc3,0x6,0x4,0x5,0xfd,0x70,
+ 0x68,0xfd,0x36,0x18,0x0,0x78,0xfe,0x0,0x20,0xf3,0xe1,
+ 0xc1,0xf1,0xc9,0x53,0x70,0x65,0x63,0x69,0x61,0x6c,0x69,
+ 0x78,0x20,0x53,0x4c,0x58,0x4f,0x53,0x20,0x2d,0x20,0x44,
+ 0x6f,0x77,0x6e,0x6c,0x6f,0x61,0x64,0x20,0x43,0x6f,0x64,
+ 0x65,0x20,0x56,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x31,
+ 0x2e,0x33,0x34,0xd,0xa,0x43,0x6f,0x70,0x79,0x72,0x69,
+ 0x67,0x68,0x74,0x20,0x28,0x63,0x29,0x20,0x53,0x70,0x65,
+ 0x63,0x69,0x61,0x6c,0x69,0x78,0x20,0x49,0x6e,0x74,0x65,
+ 0x72,0x6e,0x61,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x20,0x31,
+ 0x39,0x38,0x38,0x2f,0x38,0x39,0x2f,0x39,0x30,0x2f,0x39,
+ 0x31,0x2f,0x39,0x32,0x2f,0x39,0x33,0xd,0xa,0x41,0x6c,
+ 0x6c,0x20,0x72,0x69,0x67,0x68,0x74,0x73,0x20,0x72,0x65,
+ 0x73,0x65,0x72,0x76,0x65,0x64,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x42,0x41,0x82,0x4,0x16,0x0,
+ 0x41,0x0,0x41,0x4,0x82,0x3,0x41,0x3,0x82,0x2,0x4e,
+ 0x2,0x41,0x2,0x82,0x1,0x57,0x2,0x41,0x1,0x82,0x0,
+ 0x2b,0x0,0xa3,0x4,0x1b,0x0,0x51,0x0,0x51,0x4,0xa3,
+ 0x3,0x51,0x3,0xa3,0x2,0x62,0x2,0x51,0x2,0xa3,0x1,
+ 0x6d,0x2,0x51,0x1,0xa3,0x0,0x36,0x0,0x49,0x4e,0x0,
+ 0x0,0x1e,0x1,0x18,0x2,0x1e,0x0,0xdd,0xd1,0x7c,0x18,
+ 0xf5,0xdd,0xe5,0x21,0x80,0x80,0x54,0xfd,0x7b,0x8,0x0,
+ 0xfd,0xed,0x3c,0x6,0x0,0xfe,0x24,0x28,0x4,0x6,0x4,
+ 0x18,0x2,0x6,0x0,0xfd,0x70,0x7f,0xcb,0x43,0x20,0x5,
+ 0xfd,0x7e,0x6a,0x18,0x3,0xfd,0x7e,0x6b,0x4f,0xcb,0x7f,
+ 0xca,0x4c,0x19,0xe6,0x3,0xfd,0x77,0x68,0xed,0x3a,0x8,
+ 0x0,0xb0,0xcb,0x27,0x85,0x6f,0xdd,0xed,0x3c,0x2,0x0,
+ 0xcb,0x43,0xc2,0x7e,0x19,0xd9,0xdd,0x6e,0xac,0xdd,0x7e,
+ 0xad,0x95,0x4f,0xe6,0xc,0xfe,0xc,0x28,0x6,0x79,0xe6,
+ 0x30,0xca,0xaf,0x1a,0xdd,0x7e,0xa9,0xe6,0x5,0xc2,0x5c,
+ 0x1a,0x79,0xcb,0x7f,0x20,0x5,0xfe,0xc,0xfa,0xa0,0x1a,
+ 0xdd,0x79,0xfd,0x77,0x63,0x2c,0xdd,0x79,0xfd,0x77,0x63,
+ 0x2c,0xdd,0x79,0xfd,0x77,0x63,0x2c,0xdd,0x79,0xfd,0x77,
+ 0x63,0x2c,0xdd,0x79,0xfd,0x77,0x63,0x2c,0xdd,0x79,0xfd,
+ 0x77,0x63,0x2c,0xdd,0x79,0xfd,0x77,0x63,0x2c,0xdd,0x79,
+ 0xfd,0x77,0x63,0x2c,0xdd,0x79,0xfd,0x77,0x63,0x2c,0xdd,
+ 0x79,0xfd,0x77,0x63,0x2c,0xdd,0x79,0xfd,0x77,0x63,0x2c,
+ 0xdd,0x79,0xfd,0x77,0x63,0x2c,0xdd,0x75,0xac,0xd9,0x79,
+ 0xe6,0x3f,0xcb,0x43,0x20,0x30,0xfd,0x77,0x6a,0x62,0x2e,
+ 0x80,0xcb,0x50,0x28,0x5,0x6,0x0,0xc3,0xa2,0x18,0xdd,
+ 0xed,0x3a,0x2,0x0,0xdd,0x66,0xff,0xfd,0xed,0xf7,0x80,
+ 0x0,0xc2,0x8e,0x18,0xdd,0xe1,0xf1,0xed,0x55,0xfd,0x7e,
+ 0x62,0xed,0xb,0x2c,0x10,0xf8,0x18,0x2a,0x49,0x4e,0xfd,
+ 0x77,0x6b,0x18,0xce,0xd9,0xfd,0x7e,0x43,0xfe,0x7,0x28,
+ 0x57,0x26,0x1,0xdd,0x7e,0xab,0xdd,0x6e,0xaa,0x95,0x3d,
+ 0x4f,0xfd,0x46,0xe,0x58,0xcb,0x7f,0x20,0x4,0xb8,0xfa,
+ 0xc9,0x19,0x16,0x0,0x18,0xcc,0xdd,0x3e,0xc4,0x5,0x1,
+ 0x7a,0xfe,0x0,0x20,0x2a,0xdd,0xcb,0xa8,0x5e,0x28,0x10,
+ 0x79,0xcb,0x7f,0x20,0xb,0xfe,0x40,0xfa,0xc1,0x19,0x93,
+ 0xfe,0x40,0xfa,0xee,0x19,0xdd,0x75,0xaa,0x26,0x0,0xc3,
+ 0x41,0x19,0xfe,0x0,0x28,0x9,0x16,0x1,0x78,0x91,0x5f,
+ 0x41,0x18,0x98,0x43,0xfd,0x7e,0x62,0x10,0xfb,0x18,0xe4,
+ 0xdd,0xcb,0xb9,0xc6,0xdd,0x3e,0xc5,0x5,0x1,0xfd,0x7e,
+ 0x62,0xfd,0x7e,0x62,0x18,0xd6,0xdd,0xcb,0xba,0x5e,0x28,
+ 0x1f,0xdd,0xcb,0xa8,0x6e,0x20,0x19,0xfd,0x7e,0x5,0xfe,
+ 0x0,0x20,0xa,0xfd,0x36,0x5,0x24,0xdd,0xcb,0xa8,0xee,
+ 0x18,0x8,0xdd,0xcb,0xa8,0xfe,0xdd,0xcb,0xa8,0xf6,0xdd,
+ 0xcb,0xa8,0xe6,0xdd,0xcb,0xb4,0x7e,0x28,0x15,0xdd,0x7e,
+ 0xc4,0xe6,0x8,0x20,0x6,0xfd,0x36,0x6c,0x0,0x18,0x8,
+ 0xfd,0x7e,0x6,0xe6,0xef,0xfd,0x77,0x6,0xdd,0xcb,0xba,
+ 0x76,0x28,0x89,0xdd,0x7e,0xc4,0xe6,0x8,0x20,0xa,0xfd,
+ 0x7e,0x6,0xe6,0xef,0xfd,0x77,0x6,0x18,0x4,0xfd,0x36,
+ 0x6c,0x0,0xdd,0xcb,0xa8,0xee,0xdd,0xcb,0xa8,0xbe,0xdd,
+ 0xcb,0xa8,0xb6,0xc3,0xc1,0x19,0xdd,0xcb,0xa9,0x46,0x28,
+ 0x13,0xdd,0xcb,0xa9,0xce,0xdd,0xcb,0xa9,0x86,0xfd,0x7e,
+ 0x6,0xe6,0xf9,0xfd,0x77,0x6,0xc3,0x3e,0x19,0x79,0xcb,
+ 0x7f,0x20,0xc,0xfe,0xc,0xf2,0x86,0x1a,0xfe,0x0,0x28,
+ 0x52,0x47,0x18,0x2,0x6,0xc,0xdd,0x79,0xfe,0xa,0x28,
+ 0x8,0xfd,0x77,0x63,0x2c,0x10,0xf4,0x18,0x3f,0xfd,0x36,
+ 0x63,0xd,0xfd,0x36,0x63,0xa,0x18,0xf1,0xfe,0x0,0x28,
+ 0x31,0x47,0xdd,0x79,0xfd,0x77,0x63,0x2c,0x10,0xf8,0x18,
+ 0x26,0x79,0xe6,0xc0,0xfe,0x40,0x20,0x13,0xdd,0xcb,0xa9,
+ 0x5e,0xca,0xe4,0x18,0xdd,0xcb,0xa9,0x9e,0xdd,0x3e,0xc5,
+ 0x5,0x1,0xc3,0xe4,0x18,0xfe,0xc0,0xc2,0xe4,0x18,0xdd,
+ 0xcb,0xa9,0xde,0xc3,0xe4,0x18,0xfd,0x7e,0x6,0xe6,0xf9,
+ 0xfd,0x77,0x6,0xdd,0xcb,0xa8,0x86,0xc3,0x3e,0x19,0xdd,
+ 0xd1,0x7c,0x18,0xf5,0xc5,0xd5,0xe5,0xfd,0xe5,0xdd,0xe5,
+ 0x21,0x80,0x80,0x54,0xfd,0x7b,0x8,0x0,0xfd,0xed,0x3c,
+ 0x6,0x0,0xfe,0x24,0x28,0x4,0x6,0x4,0x18,0x2,0x6,
+ 0x0,0x78,0xed,0x3b,0x1a,0x0,0xfd,0x70,0x7f,0xfd,0x7e,
+ 0x69,0xcb,0x7f,0x28,0x2c,0xfd,0x5e,0x68,0xe6,0x3,0xfd,
+ 0x77,0x68,0xed,0x3a,0xa,0x0,0xb0,0xcb,0x27,0x85,0x6f,
+ 0xed,0x26,0xe5,0xdd,0xe1,0xc5,0xcd,0x6,0x9,0xdd,0x3e,
+ 0xc5,0x5,0x1,0xdd,0xcb,0xb9,0xce,0xfd,0x7e,0x69,0xe6,
+ 0x3f,0xfd,0x77,0x69,0xc1,0x62,0x2e,0x80,0xcb,0x50,0x28,
+ 0x4,0x6,0x0,0x18,0xba,0xe5,0xdd,0xe1,0xdd,0x66,0x1,
+ 0xfd,0xed,0xf7,0x80,0x0,0x20,0x99,0xdd,0xe1,0xfd,0xe1,
+ 0xe1,0xd1,0xc1,0xf1,0xed,0x55,0xe5,0x21,0xe8,0x3,0x2b,
+ 0xfd,0xed,0xf7,0x0,0x0,0x20,0xf8,0xe1,0xc9,0xcd,0xf5,
+ 0x8,0xdd,0x7e,0xc7,0xfe,0x1,0xc2,0x16,0x1c,0xfd,0x36,
+ 0x6f,0x3,0xcd,0x64,0x1b,0xfd,0x7e,0x6f,0xe6,0x20,0x20,
+ 0x7,0xdd,0x36,0xc8,0x9,0xc3,0x16,0x1c,0xfd,0x36,0x6f,
+ 0x2,0xcd,0x64,0x1b,0xfd,0x7e,0x6f,0xe6,0x20,0x28,0x6,
+ 0xdd,0x36,0xc8,0xa,0x18,0x70,0xfd,0x36,0x6f,0x6,0xcd,
+ 0x64,0x1b,0xfd,0x7e,0x6f,0xe6,0x10,0x20,0x6,0xdd,0x36,
+ 0xc8,0xb,0x18,0x5c,0xfd,0x36,0x6f,0x2,0xcd,0x64,0x1b,
+ 0xfd,0x7e,0x6f,0xe6,0x20,0x28,0x6,0xdd,0x36,0xc8,0xa,
+ 0x18,0x48,0x6,0x8,0xfd,0x36,0x6f,0x2,0xcd,0x64,0x1b,
+ 0xfd,0x36,0x6f,0x0,0xcd,0x64,0x1b,0xfd,0x7e,0x6f,0xe6,
+ 0x80,0x20,0x28,0x10,0xe9,0xfd,0x36,0x6f,0x2,0xcd,0x64,
+ 0x1b,0xfd,0x36,0x6f,0x0,0x21,0xe8,0x3,0xfd,0x7e,0x6f,
+ 0xe6,0x40,0x20,0x16,0x2b,0xfd,0xed,0xf7,0x0,0x0,0x20,
+ 0xf1,0xdd,0x36,0xc8,0xd,0xdd,0x77,0xb8,0x18,0x9,0xdd,
+ 0x70,0xc8,0x18,0x4,0xdd,0x36,0xc8,0x0,0xcd,0x64,0x1b,
+ 0xfd,0x36,0x6f,0x2,0xcd,0x64,0x1b,0xfd,0x36,0x6f,0x0,
+ 0xfd,0x36,0x5,0x80,0xdd,0x36,0xae,0x0,0xc9,0xcd,0xf5,
+ 0x8,0xdd,0xcb,0xa9,0x4e,0x20,0x23,0xdd,0xcb,0xa9,0xc6,
+ 0xdd,0x7e,0xc7,0xfe,0x1,0x28,0xf,0xfd,0x7e,0x6,0xf6,
+ 0x2,0xe6,0xfb,0xfd,0x77,0x6,0x26,0x0,0xc3,0xc,0xd,
+ 0xfd,0x36,0x6,0x84,0x26,0x0,0xc3,0xc,0xd,0xfd,0x7e,
+ 0x6,0xe6,0xf9,0xfd,0x77,0x6,0xfd,0x7e,0x9,0xf6,0x20,
+ 0xfd,0x77,0x9,0xfd,0x7e,0x50,0xfd,0x77,0x65,0xfd,0x36,
+ 0x63,0x0,0xfd,0x36,0x63,0x81,0xfd,0x36,0x12,0x2,0xdd,
+ 0x36,0xae,0x12,0xdd,0x3e,0xc5,0x5,0x1,0x26,0x0,0xc3,
+ 0xc,0xd,0xcd,0xf5,0x8,0xdd,0x7e,0xc5,0xfe,0x1,0x28,
+ 0x27,0xfd,0x7e,0x12,0xfe,0x0,0x28,0x5,0x26,0x0,0xc3,
+ 0xc,0xd,0xfd,0x7e,0x50,0xfd,0x77,0x65,0xfd,0x36,0x63,
+ 0x0,0xfd,0x36,0x63,0x83,0xfd,0x36,0x12,0x2,0xdd,0x36,
+ 0xc5,0x1,0x26,0x0,0xc3,0xc,0xd,0xfd,0x7e,0x12,0xfe,
+ 0x0,0x28,0x5,0x26,0x0,0xc3,0xc,0xd,0xfd,0x7e,0x6,
+ 0xf6,0x4,0xe6,0xfd,0xfd,0x77,0x6,0xfd,0x7e,0x9,0xe6,
+ 0xdf,0xfd,0x77,0x9,0xdd,0x36,0xae,0x0,0xdd,0x3e,0xc5,
+ 0x5,0x1,0xdd,0x36,0xc5,0x0,0x26,0x0,0xc3,0xc,0xd,
+ 0x26,0x0,0xdd,0x7e,0xac,0xdd,0x96,0xad,0x28,0x4,0xf1,
+ 0xc3,0x1d,0xd,0xcd,0xf5,0x8,0xdd,0x7e,0xbf,0xfe,0x1,
+ 0x28,0x4d,0xdd,0xcb,0xa9,0x4e,0x28,0x26,0xed,0x2c,0xa4,
+ 0xff,0xdd,0x7e,0xa7,0xfe,0x4,0xf2,0x21,0x1d,0xfd,0x1d,
+ 0x1c,0x0,0x20,0x35,0xf6,0x10,0xfd,0x77,0x7f,0x18,0x2e,
+ 0xfd,0x1d,0x1d,0x0,0x20,0x28,0xf6,0x40,0xfd,0x77,0x7f,
+ 0x18,0x21,0xdd,0x7e,0xc9,0xfe,0x1,0x20,0x10,0xdd,0xcb,
+ 0xa9,0xc6,0xdd,0x7e,0xc7,0xfe,0x1,0x28,0xa,0xfd,0x36,
+ 0x6,0x92,0xc9,0xdd,0xcb,0xa9,0xce,0xc9,0xfd,0x36,0x6,
+ 0x94,0xc9,0xdd,0x36,0xaa,0x0,0xdd,0x36,0xab,0x0,0xdd,
+ 0x36,0xac,0x0,0xdd,0x36,0xad,0x0,0xdd,0x36,0xc9,0x0,
+ 0xcd,0xf5,0x8,0xfd,0x7e,0x5,0xfe,0x0,0xc0,0xdd,0xcb,
+ 0xa9,0x8e,0xdd,0x7e,0xc7,0xfe,0x1,0x20,0x6,0xfd,0x36,
+ 0x5,0x14,0x18,0x32,0xdd,0xcb,0xb7,0x46,0x20,0x11,0xdd,
+ 0x7e,0xc4,0xe6,0x8,0x20,0x6,0xfd,0x36,0x6c,0x0,0x18,
+ 0x4,0xfd,0x36,0x6d,0x0,0xdd,0xcb,0xb7,0x4e,0x20,0x11,
+ 0xdd,0x7e,0xc4,0xe6,0x8,0x20,0x6,0xfd,0x36,0x6d,0x0,
+ 0x18,0x4,0xfd,0x36,0x6c,0x0,0xfd,0x36,0x5,0x80,0xfd,
+ 0x36,0x6,0x0,0xdd,0x36,0xbf,0x1,0xdd,0x36,0xae,0x10,
+ 0xdd,0x3e,0xc5,0x5,0x1,0xc9,0x2,0x44,0x2,0x44,0x2,
+ 0x40,0x2,0x40,0x2,0x40,0x2,0x40,0x2,0x44,0x2,0x44,
+ 0x2,0x44,0x2,0x44,0x2,0x44,0x2,0x40,0x2,0x40,0x2,
+ 0x44,0x2,0x44,0x20,0x1e,0x44,0x3,0x44,0x2,0x44,0x2,
+ 0x44,0x1,0x40,0x20,0x14,0x44,0x3,0x40,0x12,0x44,0x5,
+ 0x40,0x3,0x40,0x16,0x44,0x2,0x40,0x7,0x44,0xa,0x40,
+ 0x5,0x40,0x11,0x40,0x20,0x3,0x40,0x18,0x44,0x12,0x44,
+ 0x9,0x44,0x2,0x44,0x20,0x46,0x40,0x17,0x44,0x6,0x44,
+ 0x6,0x44,0x3,0x44,0x4,0x44,0xd,0x44,0x2,0x44,0x6,
+ 0x44,0x2,0x44,0x20,0x40,0x44,0x5,0x44,0x7,0x44,0x18,
+ 0x44,0x20,0xc,0x44,0x6,0x44,0x2,0x44,0x1,0x44,0xf,
+ 0x44,0x15,0x44,0x8,0x44,0xd,0x44,0x1d,0x44,0x1,0x44,
+ 0x14,0x40,0x8,0x40,0x3,0x44,0x6,0x40,0x3,0x44,0x6,
+ 0x40,0x3,0x44,0x6,0x40,0x3,0x44,0xf,0x44,0x4,0x44,
+ 0xf,0x44,0x4,0x44,0x3,0x44,0x20,0x34,0x44,0x4,0x44,
+ 0x11,0x44,0x4,0x44,0x14,0x44,0x4,0x44,0x2,0x40,0x1b,
+ 0x44,0xa,0x40,0x3,0x44,0x5,0x40,0x5,0x44,0xf,0x40,
+ 0x2,0x44,0x2,0x40,0x20,0xe,0x44,0x18,0x40,0x10,0x44,
+ 0x5,0x44,0x5,0x44,0xb,0x44,0x14,0x44,0x3,0x44,0x8,
+ 0x44,0x2,0x44,0x10,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x40,0x40,0x44,0x44,0x40,0x40,0x20,0x0,0x44,0x20,0x1,
+ 0x44,0x10,0x44,0x10,0x44,0x5,0x44,0x20,0x4,0x44,0x14,
+ 0x44,0x6,0x44,0xa,0x44,0x4,0x44,0x4,0x44,0x5,0x44,
+ 0x3,0x44,0xf,0x44,0xb,0x44,0x3,0x44,0x3,0x44,0x3,
+ 0x44,0xc,0x44,0x5,0x44,0x3,0x44,0x5,0x44,0xe,0x44,
+ 0x6,0x44,0xb,0x44,0x7,0x44,0x2,0x44,0x3,0x44,0x6,
+ 0x44,0xd,0x44,0x6,0x44,0x2,0x44,0x3,0x44,0x5,0x44,
+ 0x20,0x2,0x44,0x3,0x44,0x5,0x44,0x16,0x44,0x1a,0x44,
+ 0xe,0x44,0x16,0x44,0x3,0x44,0x5,0x44,0x4,0x44,0x19,
+ 0x44,0x4,0x44,0x1,0x44,0x3,0x44,0x5,0x44,0x5,0x44,
+ 0x6,0x44,0x2,0x44,0xc,0x44,0x5,0x44,0x9,0x44,0xa,
+ 0x44,0xb,0x44,0x8,0x44,0x20,0x9,0x44,0x12,0x44,0x2,
+ 0x44,0x20,0x1c,0x44,0x20,0x34,0x44,0x11,0x44,0x20,0x28,
+ 0x44,0x10,0x44,0x12,0x40,0x3,0x40,0x20,0x1,0x40,0x3,
+ 0x40,0x21,0x4f,0x44,0x20,0x4b,0x44,0x20,0x34,0x40,0x3,
+ 0x44,0xd,0x40,0x8,0x44,0x8,0x44,0x3,0x44,0x1,0x44,
+ 0x3,0x44,0x1,0x40,0x3,0x44,0x1,0x40,0x3,0x44,0x3,
+ 0x44,0x1,0x44,0xa,0x44,0xb,0x44,0x15,0x40,0x16,0x40,
+ 0x6,0x44,0xe,0x40,0x6,0x40,0x4,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x40,0x40,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
+ 0x44,0x44,0x44,0xf,0x44,0x6,0x44,0x5,0x44,0x20,0x8,
+ 0x44,0x20,0x31,0x44,0x3,0x44,0x4,0x44,0xa,0x44,0x5,
+ 0x44,0xd,0x44,0x20,0x4,0x40,0x13,0x40,0x20,0x4a,0x40,
+ 0x21,0x30,0x40,0x14,0x44,0x6,0x40,0x15,0x44,0x6,0x40,
+ 0x20,0x7f,0x40,0x20,0x22,0x40,0x20,0x61,0x40,0x20,0x25,
+ 0x40,0x20,0x3b,0x40,0x4,0x40,0x20,0xe1,0x40,0x1f,0x40,
+ 0x6,0x44,0x3,0x40,0x5,0x40,0x20,0x13,0x44,0x1d,0x40,
+ 0x20,0xe,0x44,0x2,0x40,0x2,0x40,0x3,0x44,0x20,0x5,
+ 0x40,0x2,0x40,0x3,0x44,0x1,0x44,0x1d,0x44,0x20,0x2,
+ 0x44,0x7,0x40,0x7,0x44,0x1,0x40,0x6,0x40,0x9,0x40,
+ 0x4,0x40,0x13,0x40,0x1,0x44,0x20,0x3,0x44,0xb,0x40,
+ 0xa,0x40,0x12,0x40,0x5,0x44,0x20,0x3,0x40,0x6,0x44,
+ 0x4,0x44,0x4,0x44,0x16,0x40,0x23,0x19,0x44,0x20,0xd,
+ 0x44,0x16,0x44,0x13,0x44,0x6,0x44,0x8,0x44,0x20,0x40,
+ 0x44,0xe,0x44,0x20,0x13,0x44,0x6,0x40,0x14,0x44,0x4,
+ 0x44,0x6,0x44,0x1a,0x40,0x20,0x55,0x44,0x17,0x44,0x8,
+ 0x44,0x20,0x1c,0x44,0x6,0x40,0x2,0x44,0x3,0x44,0x5,
+ 0x44,0xd,0x44,0x2,0x44,0x20,0x26,0x40,0x2,0x40,0x20,
+ 0x1f,0x40,0x6,0x44,0x5,0x44,0xc,0x44,0x5,0x44,0x12,
+ 0x44,0x12,0x44,0x14,0x44,0x5,0x44,0xe,0x44,0x20,0x9,
+ 0x44,0x5,0x44,0xe,0x40,0x1e,0x40,0x7,0x40,0x20,0x8,
+ 0x40,0x4,0x40,0x1,0x40,0x11,0x40,0x19,0x40,0xa,0x40,
+ 0x18,0x40,0x8,0x40,0xc,0x40,0x1,0x40,0x17,0x44,0x20,
+ 0x30,0x40,0x20,0x37,0x40,0x0,0x0,0xff,
+};
+int si_dsize = sizeof(si_download);
diff --git a/sys/i386/isa/sireg.h b/sys/i386/isa/sireg.h
new file mode 100644
index 0000000000000..6a8dd4fc88f8c
--- /dev/null
+++ b/sys/i386/isa/sireg.h
@@ -0,0 +1,69 @@
+/*
+ * Device driver for Specialix range (SLXOS) of serial line multiplexors.
+ * 'C' definitions for Specialix serial multiplex driver.
+ *
+ * Copyright (C) 1990, 1992 Specialix International,
+ * Copyright (C) 1993, Andy Rutter <andy@acronym.co.uk>
+ * Copyright (C) 1995, Peter Wemm <peter@haywire.dialix.com>
+ *
+ * Derived from: SunOS 4.x version
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notices, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Andy Rutter of
+ * Advanced Methods and Tools Ltd. based on original information
+ * from Specialix International.
+ * 4. Neither the name of Advanced Methods and Tools, nor Specialix
+ * International may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE.
+ *
+ * $Id$
+ */
+
+/*
+ * Hardware parameters which should be changed at your peril!
+ */
+
+/* Base and mask for SI Host 2.x (SIHOST2) */
+#define SIPLSIG 0x7FF8 /* Start of control space */
+#define SIPLCNTL 0x7FF8 /* Ditto */
+#define SIPLRESET SIPLCNTL /* 0 = reset */
+#define SIPLIRQ11 (SIPLCNTL+1) /* 0 = mask irq 11 */
+#define SIPLIRQ12 (SIPLCNTL+2) /* 0 = mask irq 12 */
+#define SIPLIRQ15 (SIPLCNTL+3) /* 0 = mask irq 15 */
+#define SIPLIRQSET (SIPLCNTL+4) /* 0 = interrupt host */
+#define SIPLIRQCLR (SIPLCNTL+5) /* 0 = clear irq */
+
+/* SI Host 1.x */
+#define SIRAM 0x0000 /* Ram Starts here */
+#define SIRESET 0x8000 /* Set reset */
+#define SIRESET_CL 0xc000 /* Clear reset */
+#define SIWAIT 0x9000 /* Set wait */
+#define SIWAIT_CL 0xd000 /* Set wait */
+#define SIINTCL 0xA000 /* Clear host int */
+#define SIINTCL_CL 0xE000 /* Clear host int */
+
+/*
+ * MEMSIZE is the total shared mem region
+ * RAMSIZE is value to use when probing
+ */
+#define SIHOST_MEMSIZE 0x10000
+#define SIHOST_RAMSIZE 0x8000
+#define SIHOST2_MEMSIZE 0x8000
+#define SIHOST2_RAMSIZE 0x7ff7
+#define SIEISA_MEMSIZE 0x10000
+#define SEISAT_RAMSIZE 0x10000
+
diff --git a/sys/i386/isa/sound/Readme.aedsp16 b/sys/i386/isa/sound/Readme.aedsp16
new file mode 100644
index 0000000000000..b205a9d0ff56f
--- /dev/null
+++ b/sys/i386/isa/sound/Readme.aedsp16
@@ -0,0 +1,6 @@
+Informations about Audio Excel DSP 16 can be found in the source
+file aedsp16.c
+Please, read the head of the source before using it. It contain useful
+informations.
+
+ Riccardo
diff --git a/sys/i386/isa/sound/Readme.modules b/sys/i386/isa/sound/Readme.modules
new file mode 100644
index 0000000000000..315540f510c17
--- /dev/null
+++ b/sys/i386/isa/sound/Readme.modules
@@ -0,0 +1,87 @@
+ Linux sound-driver module
+ (c) Peter Trattler
+ License: GPL (Gnu Public License)
+
+
+Idea:
+
+I've modified the sources for the sound driver to allow simply insert and
+remove the sound driver from the kernel by calling (only available for Linux)
+
+ insmod /usr/src/linux/modules/sound.o
+
+and
+
+ rmmod sound
+
+This may be useful if you are doing one of the following things:
+
+1) Debugging the sound driver
+2) Creating a new device within the sound-driver
+3) You do not the sound driver all the time (as it wastes quite a lot of
+memory for its buffers)
+
+
+Compilation:
+
+Go to /usr/src/linux and make the following steps:
+
+a) configure the sound driver: To do that call "make config" and enable the
+sound-driver -- you will be asked different questions about your
+sound-hardware (remember not to use a too big DMA-Buffer size; you
+should use 16kB, if you have 16Bit devices, otherwise you can use 32kB)
+
+b) disable the sound driver in the kernel: call make config again but answer
+'N' to "Sound card support"
+
+c) run "make modules"; the sound-driver sound.o should end up in
+/usr/src/linux/modules
+
+
+If memory is tight:
+
+I've allocated at about 70kB for the sound-drivers internal tables. If this
+is too much, 'insmod sound.o' will generate the following warning
+...
+use 'insmod memsize=xxxx'
+...
+You can only use this command, if you have (I think) at least
+modules-1.1.87 or up. You can also switch debugging on by running the command
+
+insmod sound.o debugmem=1
+
+
+Files I changed:
+
+I've only changed the files soundcard.c(most changes) and some changes within
+the Makefile, sound_config.h and the Makefile in /usr/src/linux/drivers
+
+
+Bugs:
+
+a) As the kmalloc (..., GFP_DMA) caused some unexpected errors (I don't know if
+it is my fault), I created some code, which is (by default) enabled by
+
+#define KMALLOC_DMA_BROKEN 1 (within soundcard.c).
+
+It trys to allocate a large enough region, so that the complete dma-buffer
+can be occupied in this space. If it does not fit within this region it
+doubles the size of it. But this can cause problems, if the sound-buffer is
+too big (as kmalloc can only handle regions at up to circa 100kB).
+
+So take care to use for 8Bit devices a sound-DMA-buffer of 32kB (maximum)
+and for 16Bit devices a maximum of 16kB. Otherwise the allocation scheme
+might fail.
+
+b) Buffers allocated by the different sound devices via calls to kmalloc are
+not freed, if the sound driver is removed again (these buffers tend to be
+quite small -- so it does not harm a lot)
+
+c) If there is not enough (kernel-) memory available, the installation of
+the sound-driver fails. (This happens quite often, if you did not install the
+driver right after booting -- [PS: I've only got 5MB of Ram, so this might
+be the source for this problem])
+
+
+Author:
+ Peter Trattler (peter@sbox.tu-graz.ac.at)
diff --git a/sys/i386/isa/sound/ad1848_mixer.h b/sys/i386/isa/sound/ad1848_mixer.h
new file mode 100644
index 0000000000000..9404047ce77de
--- /dev/null
+++ b/sys/i386/isa/sound/ad1848_mixer.h
@@ -0,0 +1,130 @@
+/*
+ * sound/ad1848_mixer.h
+ *
+ * Definitions for the mixer of AD1848 and compatible codecs.
+ *
+ * Copyright by Hannu Savolainen 1994
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * The AD1848 codec has generic input lines called Line, Aux1 and Aux2.
+ * Soundcard manufacturers have connected actual inputs (CD, synth, line,
+ * etc) to these inputs in different order. Therefore it's difficult
+ * to assign mixer channels to to these inputs correctly. The following
+ * contains two alternative mappings. The first one is for GUS MAX and
+ * the second is just a generic one (line1, line2 and line3).
+ * (Actually this is not a mapping but rather some kind of interleaving
+ * solution).
+ */
+#ifdef GUSMAX_MIXER
+#define MODE1_REC_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD)
+
+#define MODE1_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | \
+ SOUND_MASK_IGAIN | \
+ SOUND_MASK_PCM|SOUND_MASK_IMIX)
+
+#define MODE2_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | SOUND_MASK_SPEAKER | \
+ SOUND_MASK_IGAIN | \
+ SOUND_MASK_PCM | SOUND_MASK_IMIX)
+#else /* Generic mapping */
+#define MODE1_REC_DEVICES (SOUND_MASK_LINE3 | SOUND_MASK_MIC | \
+ SOUND_MASK_LINE1)
+
+#define MODE1_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_MIC | \
+ SOUND_MASK_LINE2 | \
+ SOUND_MASK_IGAIN | \
+ SOUND_MASK_PCM | SOUND_MASK_IMIX)
+
+#define MODE2_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_LINE2 | SOUND_MASK_MIC | \
+ SOUND_MASK_LINE3 | SOUND_MASK_SPEAKER | \
+ SOUND_MASK_IGAIN | \
+ SOUND_MASK_PCM | SOUND_MASK_IMIX)
+#endif
+
+struct mixer_def {
+ unsigned int regno: 7;
+ unsigned int polarity:1; /* 0=normal, 1=reversed */
+ unsigned int bitpos:4;
+ unsigned int nbits:4;
+};
+
+
+typedef struct mixer_def mixer_ent;
+
+/*
+ * Most of the mixer entries work in backwards. Setting the polarity field
+ * makes them to work correctly.
+ *
+ * The channel numbering used by individual soundcards is not fixed. Some
+ * cards have assigned different meanings for the AUX1, AUX2 and LINE inputs.
+ * The current version doesn't try to compensate this.
+ */
+
+#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r) \
+ {{reg_l, pola_l, pos_r, len_l}, {reg_r, pola_r, pos_r, len_r}}
+
+mixer_ent mix_devices[32][2] = { /* As used in GUS MAX */
+MIX_ENT(SOUND_MIXER_VOLUME, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6),
+MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_MIC, 0, 1, 5, 1, 1, 1, 5, 1),
+MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4),
+MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5)
+};
+
+static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
+{
+ 0x5a5a, /* Master Volume */
+ 0x3232, /* Bass */
+ 0x3232, /* Treble */
+ 0x4b4b, /* FM */
+ 0x6464, /* PCM */
+ 0x4b4b, /* PC Speaker */
+ 0x4b4b, /* Ext Line */
+ 0x1010, /* Mic */
+ 0x4b4b, /* CD */
+ 0x0000, /* Recording monitor */
+ 0x4b4b, /* SB PCM */
+ 0x4b4b, /* Recording level */
+ 0x4b4b, /* Input gain */
+ 0x4b4b, /* Output gain */
+ 0x4b4b, /* Line1 */
+ 0x4b4b, /* Line2 */
+ 0x4b4b /* Line3 */
+};
+
+#define LEFT_CHN 0
+#define RIGHT_CHN 1
diff --git a/sys/i386/isa/sound/aedsp16.c b/sys/i386/isa/sound/aedsp16.c
new file mode 100644
index 0000000000000..b14a24618f0cc
--- /dev/null
+++ b/sys/i386/isa/sound/aedsp16.c
@@ -0,0 +1,838 @@
+/*
+ sound/aedsp16.c
+
+ Audio Excel DSP 16 software configuration routines
+
+ Copyright (C) 1995 Riccardo Facchetti (riccardo@cdc8g5.cdc.polimi.it)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met: 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer. 2.
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+ READ THIS
+
+ This module is intended for Audio Excel DSP 16 Sound Card.
+
+ Audio Excel DSP 16 is an SB pro II, Microsoft Sound System
+ and MPU-401 compatible card.
+ It is software-only configurable (no jumpers to hard-set irq/dma/mpu-irq),
+ so before this module, the only way to configure the DSP under linux was
+ boot the MS-BAU loading the sound.sys device driver (this driver soft-
+ configure the sound board hardware by massaging someone of its registers),
+ and then ctrl-alt-del to boot linux with the DSP configured by the DOG
+ driver.
+
+ This module works configuring your Audio Excel DSP 16's
+ irq, dma and mpu-401-irq. The voxware probe routines rely on the
+ fact that if the hardware is there, they can detect it. The problem
+ with AEDSP16 is that no hardware can be found by the probe routines
+ if the sound card is not well configured. Sometimes the kernel probe
+ routines can find an SBPRO even when the card is not configured (this
+ is the standard setup of the card), but the SBPRO emulation don't work
+ well if the card is not properly initialized. For this reason
+
+ InitAEDSP16_...()
+
+ routines are called before the voxware probe routines try to detect the
+ hardware.
+
+ NOTE (READ THE NOTE TOO, IT CONTAIN USEFUL INFORMATIONS)
+
+ The Audio Excel DSP 16 Sound Card emulates both SBPRO and MSS;
+ the voxware sound driver can be configured for SBPRO and MSS cards
+ at the same time, but the aedsp16 can't be two cards!!
+ When we configure it, we have to choose the SBPRO or the MSS emulation
+ for AEDSP16. We also can install a *REAL* card of the other type
+ (see [1], not tested but I can't see any reason for it to fail).
+
+ NOTE: If someone can test the combination AEDSP16+MSS or AEDSP16+SBPRO
+ please let me know if it works.
+
+ The MPU-401 support can be compiled in together with one of the other
+ two operating modes.
+
+ The board configuration calls, are in the probe_...() routines because
+ we have to configure the board before probing it for a particular
+ hardware. After card configuration, we can probe the hardware.
+
+ NOTE: This is something like plug-and-play: we have only to plug
+ the AEDSP16 board in the socket, and then configure and compile
+ a kernel that uses the AEDSP16 software configuration capability.
+ No jumper setting is needed!
+
+ For example, if you want AEDSP16 to be an SBPro, on irq 10, dma 3
+ you have just to make config the voxware package, configuring
+ the SBPro sound card with that parameters, then when configure
+ asks if you have an AEDSP16, answer yes. That's it.
+ Compile the kernel and run it.
+
+ NOTE: This means that you can choose irq and dma, but not the
+ I/O addresses. To change I/O addresses you have to set them
+ with jumpers.
+
+ NOTE: InitAEDSP16_...() routines get as parameter the hw_config,
+ the hardware configuration of the - to be configured - board.
+ The InitAEDSP16() routine, configure the board following our
+ wishes, that are in the hw_config structure.
+
+ You can change the irq/dma/mirq settings WITHOUT THE NEED to open
+ your computer and massage the jumpers (there are no irq/dma/mirq
+ jumpers to be configured anyway, only I/O port ones have to be
+ configured with jumpers)
+
+ For some ununderstandable reason, the card default of irq 7, dma 1,
+ don't work for me. Seems to be an IRQ or DMA conflict. Under heavy
+ HDD work, the kernel start to erupt out a lot of messages like:
+
+ 'Sound: DMA timed out - IRQ/DRQ config error?'
+
+ For what I can say, I have NOT any conflict at irq 7 (under linux I'm
+ using the lp polling driver), and dma line 1 is unused as stated by
+ /proc/dma. I can suppose this is a bug of AEDSP16. I know my hardware so
+ I'm pretty sure I have not any conflict, but may be I'm wrong. Who knows!
+ Anyway a setting of irq 10, dma 3 works really fine.
+
+ NOTE: if someone can use AEDSP16 with irq 7, dma 1, please let me know
+ the emulation mode, all the installed hardware and the hardware
+ configuration (irq and dma settings of all the hardware).
+
+ This init module should work with SBPRO+MSS, when one of the two is
+ the AEDSP16 emulation and the other the real card. (see [1])
+ For example:
+
+ AEDSP16 (0x220) in SBPRO emu (0x220) + real MSS + other
+ AEDSP16 (0x220) in MSS emu + real SBPRO (0x240) + other
+
+ MPU401 should work. (see [1])
+
+ [1] Not tested by me for lack of hardware.
+
+ TODO, WISHES AND TECH
+
+ May be there's lot of redundant delays, but for now I want to leave it
+ this way.
+
+ Should be interesting eventually write down a new ioctl for the
+ aedsp16, to let the suser() change the irq/dma/mirq on the fly.
+ The thing is not trivial.
+ In the real world, there's no need to have such an ioctl because
+ when we configure the kernel for compile, we can choose the config
+ parameters. If we change our mind, we can easily re-config the kernel
+ and re-compile.
+ Why let the suser() change the config parameters on the fly ?
+ If anyone have a reasonable answer to this question, I will write down
+ the code to do it.
+
+ More integration with voxware, using voxware low level routines to
+ read-write dsp is not possible because you may want to have MSS
+ support and in that case we can not rely on the functions included
+ in sb_dsp.c to control 0x2yy I/O ports. I will continue to use my
+ own I/O functions.
+
+ - About I/O ports allocation -
+
+ The request_region should be done at device probe in every sound card
+ module. This module is not the best site for requesting regions.
+ When the request_region code will be added to the main modules such as
+ sb, adlib, gus, ad1848, etc, the requesting code in this module should
+ go away.
+
+ I think the request regions should be done this way:
+
+ if (check_region(...))
+ return ERR; // I/O region alredy reserved
+ device_probe(...);
+ device_attach(...);
+ request_region(...); // reserve only when we are sure all is okay
+
+ Request the 2x0h region in any case if we are using this card.
+
+ NOTE: the "(sbpro)" string with which we are requesting the aedsp16 region
+ (see code) does not mean necessarly that we are emulating sbpro.
+ It mean that the region is the sbpro I/O ports region. We use this
+ region to access the control registers of the card, and if emulating
+ sbpro, I/O sbpro registers too. If we are emulating MSS, the sbpro
+ registers are not used, in no way, to emulate an sbpro: they are
+ used only for configuration pourposes.
+
+ Someone pointed out that should be possible use both the SBPRO and MSS
+ modes because the sound card have all the two chipsets, supposing that
+ the card is really two cards. I have tried something to have the two
+ modes work together, but, for some reason unknown to me, without success.
+
+ I think all the soft-config only cards have an init sequence similar to
+ this. If you have a card that is not an aedsp16, you can try to start
+ with this module changing it (mainly in the CMD? I think) to fit your
+ needs.
+
+ Started Fri Mar 17 16:13:18 MET 1995
+
+ v0.1 (ALPHA, was an user-level program called AudioExcelDSP16.c)
+ - Initial code.
+ v0.2 (ALPHA)
+ - Cleanups.
+ - Integrated with Linux voxware v 2.90-2 kernel sound driver.
+ - SoundBlaster Pro mode configuration.
+ - Microsoft Sound System mode configuration.
+ - MPU-401 mode configuration.
+ v0.3 (ALPHA)
+ - Cleanups.
+ - Rearranged the code to let InitAEDSP16 be more general.
+ - Erased the REALLY_SLOW_IO. We don't need it. Erased the linux/io.h
+ inclusion too. We rely on os.h
+ - Used the INB and OUTB #defined in os.h instead of inb and outb.
+ - Corrected the code for GetCardName (DSP Copyright) to get a variable
+ len string (we are not sure about the len of Copyright string).
+ This works with any SB and compatible.
+ - Added the code to request_region at device init (should go in
+ the main body of voxware).
+ v0.4 (BETA)
+ - Better configure.c patch for aedsp16 configuration (better
+ logic of inclusion of AEDSP16 support)
+ - Modified the conditional compilation to better support more than
+ one sound card of the emulated type (read the NOTES above)
+ - Moved the sb init routine from the attach to the very first
+ probe in sb_card.c
+ - Rearrangemens and cleanups
+ - Wiped out some unnecessary code and variables: this is kernel
+ code so it is better save some TEXT and DATA
+ - Fixed the request_region code. We must allocate the aedsp16 (sbpro)
+ I/O ports in any case because they are used to access the DSP
+ configuration registers and we can not allow anyone to get them.
+ v0.5
+ - cleanups on comments
+ - prep for diffs against v3.0-proto-950402
+
+ */
+
+/*
+ * Include the main voxware header file. It include all the os/voxware/etc
+ * headers needed by this source.
+ */
+#include "sound_config.h"
+/*
+ * all but ioport.h :)
+ */
+#include <linux/ioport.h>
+
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AEDSP16)
+
+#define VERSION "0.5" /* Version of Audio Excel DSP 16 driver */
+
+#undef AEDSP16_DEBUG /* Define this to enable debug code */
+/* Actually no debug code is activated */
+
+/*
+ * Hardware related defaults
+ */
+#define IRQ 7 /* 5 7(default) 9 10 11 */
+#define MIRQ 0 /* 5 7 9 10 0(default), 0 means disable */
+#define DMA 1 /* 0 1(default) 3 */
+
+/*
+ * Commands of AEDSP16's DSP (SBPRO+special).
+ * For now they are CMDn, in the future they may change.
+ */
+#define CMD1 0xe3 /* Get DSP Copyright */
+#define CMD2 0xe1 /* Get DSP Version */
+#define CMD3 0x88 /* */
+#define CMD4 0x5c /* */
+#define CMD5 0x50 /* Set M&I&DRQ mask (the real config) */
+#define CMD6 0x8c /* Enable Microsoft Sound System mode */
+
+/*
+ * Offsets of AEDSP16 DSP I/O ports. The offest is added to portbase
+ * to have the actual I/O port.
+ * Register permissions are:
+ * (wo) == Write Only
+ * (ro) == Read Only
+ * (w-) == Write
+ * (r-) == Read
+ */
+#define DSP_RESET 0x06 /* offset of DSP RESET (wo) */
+#define DSP_READ 0x0a /* offset of DSP READ (ro) */
+#define DSP_WRITE 0x0c /* offset of DSP WRITE (w-) */
+#define DSP_COMMAND 0x0c /* offset of DSP COMMAND (w-) */
+#define DSP_STATUS 0x0c /* offset of DSP STATUS (r-) */
+#define DSP_DATAVAIL 0x0e /* offset of DSP DATA AVAILABLE (ro) */
+
+
+#define RETRY 10 /* Various retry values on I/O opera- */
+#define STATUSRETRY 1000 /* tions. Sometimes we have to */
+#define HARDRETRY 500000 /* wait for previous cmd to complete */
+
+/*
+ * Size of character arrays that store name and version of sound card
+ */
+#define CARDNAMELEN 15 /* Size of the card's name in chars */
+#define CARDVERLEN 2 /* Size of the card's version in chars */
+
+/*
+ * Bit mapped flags for calling InitAEDSP16(), and saving the current
+ * emulation mode.
+ */
+#define INIT_NONE (0 )
+#define INIT_SBPRO (1<<0)
+#define INIT_MSS (1<<1)
+#define INIT_MPU401 (1<<2)
+#define RESET_DSP16 (1<<3)
+
+/* Base HW Port for Audio Card */
+static int portbase = AEDSP16_BASE;
+static int irq = IRQ; /* irq for DSP I/O */
+static int mirq = MIRQ; /* irq for MPU-401 I/O */
+static int dma = DMA; /* dma for DSP I/O */
+
+/* Init status of the card */
+static int ae_init = INIT_NONE; /* (bitmapped variable) */
+static int oredparams = 0; /* Will contain or'ed values of params */
+static int gc = 0; /* generic counter (utility counter) */
+struct orVals
+ { /* Contain the values to be or'ed */
+ int val; /* irq|mirq|dma */
+ int or; /* oredparams |= TheStruct.or */
+ };
+
+/*
+ * Magic values that the DSP will eat when configuring irq/mirq/dma
+ */
+/* DSP IRQ conversion array */
+static struct orVals orIRQ[] =
+{
+ {0x05, 0x28},
+ {0x07, 0x08},
+ {0x09, 0x10},
+ {0x0a, 0x18},
+ {0x0b, 0x20},
+ {0x00, 0x00}
+};
+
+/* MPU-401 IRQ conversion array */
+static struct orVals orMIRQ[] =
+{
+ {0x05, 0x04},
+ {0x07, 0x44},
+ {0x09, 0x84},
+ {0x0a, 0xc4},
+ {0x00, 0x00}
+};
+
+/* DMA Channels conversion array */
+static struct orVals orDMA[] =
+{
+ {0x00, 0x01},
+ {0x01, 0x02},
+ {0x03, 0x03},
+ {0x00, 0x00}
+};
+
+/*
+ * Buffers to store audio card informations
+ */
+static char AudioExcelName[CARDNAMELEN + 1];
+static char AudioExcelVersion[CARDVERLEN + 1];
+
+static void
+tenmillisec (void)
+{
+
+ for (gc = 0; gc < 1000; gc++)
+ tenmicrosec ();
+}
+
+static int
+WaitForDataAvail (int port)
+{
+ int loop = STATUSRETRY;
+ unsigned char ret = 0;
+
+ do
+ {
+ ret = INB (port + DSP_DATAVAIL);
+ /*
+ * Wait for data available (bit 7 of ret == 1)
+ */
+ }
+ while (!(ret & 0x80) && loop--);
+
+ if (ret & 0x80)
+ return 0;
+
+ return -1;
+}
+
+static int
+ReadData (int port)
+{
+ if (WaitForDataAvail (port))
+ return -1;
+ return INB (port + DSP_READ);
+}
+
+static int
+CheckDSPOkay (int port)
+{
+ return ((ReadData (port) == 0xaa) ? 0 : -1);
+}
+
+static int
+ResetBoard (int port)
+{
+ /*
+ * Reset DSP
+ */
+ OUTB (1, (port + DSP_RESET));
+ tenmicrosec ();
+ OUTB (0, (port + DSP_RESET));
+ tenmicrosec ();
+ tenmicrosec ();
+ return CheckDSPOkay (port);
+}
+
+static int
+WriteDSPCommand (int port, int cmd)
+{
+ unsigned char ret;
+ int loop = HARDRETRY;
+
+ do
+ {
+ ret = INB (port + DSP_STATUS);
+ /*
+ * DSP ready to receive data if bit 7 of ret == 0
+ */
+ if (!(ret & 0x80))
+ {
+ OUTB (cmd, port + DSP_COMMAND);
+ return 0;
+ }
+ }
+ while (loop--);
+
+ printk ("[aedsp16] DSP Command (0x%x) timeout.\n", cmd);
+ return -1;
+}
+
+int
+InitMSS (int port)
+{
+
+ tenmillisec ();
+
+ if (WriteDSPCommand (port, CMD6))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD6);
+ return -1;
+ }
+
+ tenmillisec ();
+
+ return 0;
+}
+
+static int
+SetUpBoard (int port)
+{
+ int loop = RETRY;
+
+ do
+ {
+ if (WriteDSPCommand (portbase, CMD3))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD3);
+ return -1;
+ }
+
+ tenmillisec ();
+
+ }
+ while (WaitForDataAvail (port) && loop--);
+
+#if defined(THIS_SHOULD_GO_AWAY)
+ if (CheckDSPOkay (port))
+ {
+ printk ("[aedsp16] CheckDSPOkay: failed\n");
+ return -1;
+ }
+#else
+ if (ReadData (port) == -1)
+ {
+ printk ("[aedsp16] ReadData after CMD 0x%x: failed\n", CMD3);
+ return -1;
+ }
+#endif
+
+ if (WriteDSPCommand (portbase, CMD4))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD4);
+ return -1;
+ }
+
+ if (WriteDSPCommand (portbase, CMD5))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD5);
+ return -1;
+ }
+
+ if (WriteDSPCommand (portbase, oredparams))
+ {
+ printk ("[aedsp16] Initialization of (M)IRQ and DMA: failed!\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+GetCardVersion (int port)
+{
+ int len = 0;
+ int ret;
+ int ver[3];
+
+ do
+ {
+ if ((ret = ReadData (port)) == -1)
+ return -1;
+ /*
+ * We alredy know how many int are stored (2), so we know when the
+ * string is finished.
+ */
+ ver[len++] = ret;
+ }
+ while (len < CARDVERLEN);
+ sprintf (AudioExcelVersion, "%d.%d", ver[0], ver[1]);
+ return 0;
+}
+
+static int
+GetCardName (int port)
+{
+ int len = 0;
+ int ret;
+
+ do
+ {
+ if ((ret = ReadData (port)) == -1)
+ /*
+ * If no more data availabe, return to the caller, no error if len>0.
+ * We have no other way to know when the string is finished.
+ */
+ return (len ? 0 : -1);
+
+ AudioExcelName[len++] = ret;
+
+ }
+ while (len < CARDNAMELEN);
+ return 0;
+}
+
+static void
+InitializeHardParams (void)
+{
+
+ memset (AudioExcelName, 0, CARDNAMELEN + 1);
+ memset (AudioExcelVersion, 0, CARDVERLEN + 1);
+
+ for (gc = 0; orIRQ[gc].or; gc++)
+ if (orIRQ[gc].val == irq)
+ oredparams |= orIRQ[gc].or;
+
+ for (gc = 0; orMIRQ[gc].or; gc++)
+ if (orMIRQ[gc].or == mirq)
+ oredparams |= orMIRQ[gc].or;
+
+ for (gc = 0; orDMA[gc].or; gc++)
+ if (orDMA[gc].val == dma)
+ oredparams |= orDMA[gc].or;
+}
+
+static int
+InitAEDSP16 (int which)
+{
+ static char *InitName = NULL;
+
+ InitializeHardParams ();
+
+ if (ResetBoard (portbase))
+ {
+ printk ("[aedsp16] ResetBoard: failed!\n");
+ return -1;
+ }
+
+#if defined(THIS_SHOULD_GO_AWAY)
+ if (CheckDSPOkay (portbase))
+ {
+ printk ("[aedsp16] CheckDSPOkay: failed!\n");
+ return -1;
+ }
+#endif
+
+ if (WriteDSPCommand (portbase, CMD1))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD1);
+ return -1;
+ }
+
+ if (GetCardName (portbase))
+ {
+ printk ("[aedsp16] GetCardName: failed!\n");
+ return -1;
+ }
+
+ /*
+ * My AEDSP16 card return SC-6000 in AudioExcelName, so
+ * if we have something different, we have to be warned.
+ */
+ if (strcmp ("SC-6000", AudioExcelName))
+ printk ("[aedsp16] Warning: non SC-6000 audio card!\n");
+
+ if (WriteDSPCommand (portbase, CMD2))
+ {
+ printk ("[aedsp16] CMD 0x%x: failed!\n", CMD2);
+ return -1;
+ }
+
+ if (GetCardVersion (portbase))
+ {
+ printk ("[aedsp16] GetCardVersion: failed!\n");
+ return -1;
+ }
+
+ if (SetUpBoard (portbase))
+ {
+ printk ("[aedsp16] SetUpBoard: failed!\n");
+ return -1;
+ }
+
+ if (which == INIT_MSS)
+ {
+ if (InitMSS (portbase))
+ {
+ printk ("[aedsp16] Can't initialize Microsoft Sound System mode.\n");
+ return -1;
+ }
+ }
+
+ /*
+ * If we are resetting, do not print any message because we may be
+ * in playing and we do not want lost too much time.
+ */
+ if (!(which & RESET_DSP16))
+ {
+ if (which & INIT_MPU401)
+ InitName = "MPU401";
+ else if (which & INIT_SBPRO)
+ InitName = "SBPro";
+ else if (which & INIT_MSS)
+ InitName = "MSS";
+ else
+ InitName = "None";
+
+ printk ("Audio Excel DSP 16 init v%s (%s %s) [%s]\n",
+ VERSION, AudioExcelName,
+ AudioExcelVersion, InitName);
+ }
+
+ tenmillisec ();
+
+ return 0;
+}
+
+#if defined(AEDSP16_SBPRO)
+
+int
+InitAEDSP16_SBPRO (struct address_info *hw_config)
+{
+ /*
+ * If the card is alredy init'ed MSS, we can not init it to SBPRO too
+ * because the board can not emulate simultaneously MSS and SBPRO.
+ */
+ if (ae_init & INIT_MSS)
+ return -1;
+ if (ae_init & INIT_SBPRO)
+ return 0;
+
+ /*
+ * For now we will leave this
+ * code included only when INCLUDE_AEDSP16 is configured in, but it should
+ * be better include it every time.
+ */
+ if (!(ae_init & INIT_MPU401))
+ {
+ if (check_region (hw_config->io_base, 0x0f))
+ {
+ printk ("AEDSP16/SBPRO I/O port region is alredy in use.\n");
+ return -1;
+ }
+ }
+
+ /*
+ * Set up the internal hardware parameters, to let the driver reach
+ * the Sound Card.
+ */
+ portbase = hw_config->io_base;
+ irq = hw_config->irq;
+ dma = hw_config->dma;
+ if (InitAEDSP16 (INIT_SBPRO))
+ return -1;
+
+ if (!(ae_init & INIT_MPU401))
+ request_region (hw_config->io_base, 0x0f, "aedsp16 (sbpro)");
+
+ ae_init |= INIT_SBPRO;
+ return 0;
+}
+
+#endif /* AEDSP16_SBPRO */
+
+#if defined(AEDSP16_MSS)
+
+int
+InitAEDSP16_MSS (struct address_info *hw_config)
+{
+ /*
+ * If the card is alredy init'ed SBPRO, we can not init it to MSS too
+ * because the board can not emulate simultaneously MSS and SBPRO.
+ */
+ if (ae_init & INIT_SBPRO)
+ return -1;
+ if (ae_init & INIT_MSS)
+ return 0;
+
+ /*
+ * For now we will leave this
+ * code included only when INCLUDE_AEDSP16 is configured in, but it should
+ * be better include it every time.
+ */
+ if (check_region (hw_config->io_base, 0x08))
+ {
+ printk ("MSS I/O port region is alredy in use.\n");
+ return -1;
+ }
+
+ /*
+ * We must allocate the AEDSP16 region too because these are the I/O ports
+ * to access card's control registers.
+ */
+ if (!(ae_init & INIT_MPU401))
+ {
+ if (check_region (AEDSP16_BASE, 0x0f))
+ {
+ printk ("AEDSP16 I/O port region is alredy in use.\n");
+ return -1;
+ }
+ }
+
+
+ /*
+ * If we are configuring the card for MSS, the portbase for card configuration
+ * is the default one (0x220 unless you have changed the factory default
+ * with board switches), so no need to modify the portbase variable.
+ * The default is AEDSP16_BASE, that is the right value.
+ */
+ irq = hw_config->irq;
+ dma = hw_config->dma;
+ if (InitAEDSP16 (INIT_MSS))
+ return -1;
+
+ request_region (hw_config->io_base, 0x08, "aedsp16 (mss)");
+
+ if (!(ae_init & INIT_MPU401))
+ request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
+
+ ae_init |= INIT_MSS;
+ return 0;
+}
+
+#endif /* AEDSP16_MSS */
+
+#if defined(AEDSP16_MPU401)
+
+int
+InitAEDSP16_MPU401 (struct address_info *hw_config)
+{
+ if (ae_init & INIT_MPU401)
+ return 0;
+
+ /*
+ * For now we will leave this
+ * code included only when INCLUDE_AEDSP16 is configured in, but it should
+ * be better include it every time.
+ */
+ if (check_region (hw_config->io_base, 0x02))
+ {
+ printk ("SB I/O port region is alredy in use.\n");
+ return -1;
+ }
+
+ /*
+ * We must allocate the AEDSP16 region too because these are the I/O ports
+ * to access card's control registers.
+ */
+ if (!(ae_init & (INIT_MSS | INIT_SBPRO)))
+ {
+ if (check_region (AEDSP16_BASE, 0x0f))
+ {
+ printk ("AEDSP16 I/O port region is alredy in use.\n");
+ return -1;
+ }
+ }
+
+ /*
+ * If mpu401, the irq and dma are not important, do not touch it
+ * because we may use the default if sbpro is not yet configured,
+ * we may use the sbpro ones if configured, and nothing wrong
+ * should happen.
+ *
+ * The mirq default is 0, but once set it to non-0 value, we should
+ * not touch it anymore (unless I write an ioctl to do it, of course).
+ */
+ mirq = hw_config->irq;
+ if (InitAEDSP16 (INIT_MPU401))
+ return -1;
+
+ request_region (hw_config->io_base, 0x02, "aedsp16 (mpu401)");
+
+ if (!(ae_init & (INIT_MSS | INIT_SBPRO)))
+ request_region (AEDSP16_BASE, 0x0f, "aedsp16 (sbpro)");
+
+ ae_init |= INIT_MPU401;
+ return 0;
+}
+
+#endif /* AEDSP16_MPU401 */
+
+#if 0 /* Leave it out for now. We are not using this portion of code. */
+
+/*
+ * Entry point for a reset function.
+ * May be I will write the infamous ioctl :)
+ */
+int
+ResetAEDSP16 (void)
+{
+#if defined(AEDSP16_DEBUG)
+ printk ("[aedsp16] ResetAEDSP16 called.\n");
+#endif
+ return InitAEDSP16 (RESET_DSP16);
+}
+
+#endif /* 0 */
+
+#endif /* !EXCLUDE_AEDSP16 */
diff --git a/sys/i386/isa/sound/coproc.h b/sys/i386/isa/sound/coproc.h
new file mode 100644
index 0000000000000..f9023821d3f25
--- /dev/null
+++ b/sys/i386/isa/sound/coproc.h
@@ -0,0 +1,12 @@
+/*
+ * Definitions for various on board processors on the soundcards. For
+ * example DSP processors.
+ */
+
+/*
+ * Coprocessor access types
+ */
+#define COPR_CUSTOM 0x0001 /* Custom applications */
+#define COPR_MIDI 0x0002 /* MIDI (MPU-401) emulation */
+#define COPR_PCM 0x0004 /* Digitized voice applications */
+#define COPR_SYNTH 0x0008 /* Music synthesis */
diff --git a/sys/i386/isa/sound/hex2hex.h b/sys/i386/isa/sound/hex2hex.h
new file mode 100644
index 0000000000000..ecd7b4c4239c6
--- /dev/null
+++ b/sys/i386/isa/sound/hex2hex.h
@@ -0,0 +1,97 @@
+/*
+ * This file is a part of configure.c
+ *
+ * hex2hex reads an input file in Intel HEX format and produces
+ * an (unsigned char) array which contains the bytes and writes it to the
+ * output file using C syntax
+ */
+
+#define MAX_SIZE (256*1024)
+#define ABANDON(why) { \
+ fprintf(stderr, "%s: " why "\n", source); \
+ fclose(inf);fclose(outf);return 0; \
+ }
+
+int hex2hex(char *source, char *target, char *varline)
+{
+ FILE *inf, *outf;
+
+ int i,l, c;
+ unsigned char buf[MAX_SIZE];
+
+ if ((inf=fopen(source, "r"))==NULL)
+ {
+ perror(source);
+ return 0;
+ }
+
+ if ((outf=fopen(target, "w"))==NULL)
+ {
+ perror(target);
+ fclose(inf);
+ return 0;
+ }
+
+ l=0;
+
+ while ((c=getc(inf))!=EOF)
+ {
+ if (c == ':') /* Sync with beginning of line */
+ {
+ int n, check;
+ unsigned char sum;
+ int addr;
+ int linetype;
+
+ if (fscanf(inf, "%02x", &n) != 1)
+ ABANDON("File format error");
+ sum = n;
+
+ if (fscanf(inf, "%04x", &addr) != 1)
+ ABANDON("File format error");
+ sum += addr/256;
+ sum += addr%256;
+
+ if (fscanf(inf, "%02x", &linetype) != 1)
+ ABANDON("File format error");
+ sum += linetype;
+
+ if (linetype != 0)
+ continue;
+
+ for (i=0;i<n;i++)
+ {
+ if (fscanf(inf, "%02x", &c) != 1)
+ ABANDON("File format error");
+ if (addr >= MAX_SIZE)
+ ABANDON("File too large");
+ buf[addr++] = c;
+ if (addr > l)
+ l = addr;
+ sum += c;
+ }
+
+ if (fscanf(inf, "%02x", &check) != 1)
+ ABANDON("File format error");
+
+ sum = ~sum + 1;
+ if (check != sum)
+ ABANDON("Line checksum error");
+ }
+ }
+
+ fprintf(outf, "/*\n *\t Computer generated file. Do not edit.\n */\n");
+ fprintf(outf, "%s[] = {\n", varline);
+
+ for (i=0;i<l;i++)
+ {
+ if (i) fprintf(outf, ",");
+ if (i && !(i % 16)) fprintf(outf, "\n");
+ fprintf(outf, "0x%02x", buf[i]);
+ }
+
+ fprintf(outf, "\n};\n\n");
+ fclose(inf);
+ fclose(outf);
+ return 1;
+}
diff --git a/sys/i386/isa/sound/mad16.h b/sys/i386/isa/sound/mad16.h
new file mode 100644
index 0000000000000..0370973667a40
--- /dev/null
+++ b/sys/i386/isa/sound/mad16.h
@@ -0,0 +1,91 @@
+
+/*
+ * Initialization code for OPTI MAD16 interface chip by
+ * Davor Jadrijevic <davor@emard.pub.hr>
+ * (Included by ad1848.c when MAD16 support is enabled)
+ *
+ * It looks like MAD16 is similar than the Mozart chip (OAK OTI-601).
+ * It could be even possible that these chips are exactly the same. Can
+ * anybody confirm this?
+ */
+
+static void wr_a_mad16(int base, int v, int a)
+{
+ OUTB(a, base + 0xf);
+ OUTB(v, base + 0x11);
+}
+
+static void wr_b_mad16(int base, int v, int a)
+{
+ OUTB(a, base + 0xf);
+ OUTB(v, base + 0xd);
+}
+
+/*
+static int rd_a_mad16(int base, int a)
+{
+ OUTB(a, base + 0xf);
+ return INB(base + 0x11);
+}
+*/
+
+static int rd_b_mad16(int base, int a)
+{
+ OUTB(a, base + 0xf);
+ return INB(base + 0xd);
+}
+
+/*
+static int rd_0_mad16(int base, int a)
+{
+ OUTB(a, base + 0xf);
+ return INB(base + 0xf);
+}
+
+static void wr_ad(int base, int v, int a)
+{
+ OUTB(a, base + 4);
+ OUTB(v, base + 5);
+}
+
+static int rd_ad(int base, int a)
+{
+ OUTB(a, base + 4);
+ return INB(base + 5);
+}
+*/
+
+static int mad16init(int adr)
+{
+ int j;
+ long i;
+
+ static int ad1848_bases[] =
+{ 0x220, -1, -1, 0x240, -1, -1, -1, -1, 0x530, 0xE80, 0xF40, 0x604, 0 };
+
+ int mad16_base = 0xf80, ad1848_base;
+
+
+ for(j = 0; (j < 16) && (ad1848_bases[j] != 0); j++)
+ if(adr == ad1848_bases[j])
+ break;
+
+ if( (ad1848_base = ad1848_bases[j]) < 0x530)
+ {
+ printk("Unknown MAD16 setting 0x%3X\n", adr);
+ return -1;
+ }
+
+ /* printk("OPTi MAD16 WSS at 0x%3X\n", ad1848_base); */
+
+ rd_b_mad16(mad16_base, 0xe2);
+ wr_a_mad16(mad16_base, 0x1a, 0xe2);
+ wr_b_mad16(mad16_base, j * 16 + 1, 0xe2);
+ wr_a_mad16(mad16_base, 0x1a, 0xe2);
+ for( i = 0; i < 10000; i++)
+ if( (INB(ad1848_base+4) & 0x80) == 0 )
+ break;
+
+ return 0;
+};
+
diff --git a/sys/i386/isa/sound/soundvers.h b/sys/i386/isa/sound/soundvers.h
new file mode 100644
index 0000000000000..ca892e8259da1
--- /dev/null
+++ b/sys/i386/isa/sound/soundvers.h
@@ -0,0 +1 @@
+#define SOUND_VERSION_STRING "3.0-beta-950506"
diff --git a/sys/i386/isa/sound/sscape.c b/sys/i386/isa/sound/sscape.c
new file mode 100644
index 0000000000000..9204b188aab87
--- /dev/null
+++ b/sys/i386/isa/sound/sscape.c
@@ -0,0 +1,1120 @@
+/*
+ * sound/sscape.c
+ *
+ * Low level driver for Ensoniq Soundscape
+ *
+ * Copyright by Hannu Savolainen 1994
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "sound_config.h"
+
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SSCAPE)
+
+#include "coproc.h"
+
+/*
+ * I/O ports
+ */
+#define MIDI_DATA 0
+#define MIDI_CTRL 1
+#define HOST_CTRL 2
+#define TX_READY 0x02
+#define RX_READY 0x01
+#define HOST_DATA 3
+#define ODIE_ADDR 4
+#define ODIE_DATA 5
+
+/*
+ * Indirect registers
+ */
+#define GA_INTSTAT_REG 0
+#define GA_INTENA_REG 1
+#define GA_DMAA_REG 2
+#define GA_DMAB_REG 3
+#define GA_INTCFG_REG 4
+#define GA_DMACFG_REG 5
+#define GA_CDCFG_REG 6
+#define GA_SMCFGA_REG 7
+#define GA_SMCFGB_REG 8
+#define GA_HMCTL_REG 9
+
+/*
+ * DMA channel identifiers (A and B)
+ */
+#define SSCAPE_DMA_A 0
+#define SSCAPE_DMA_B 1
+
+#define PORT(name) (devc->base+name)
+
+/*
+ * Host commands recognized by the OBP microcode
+ */
+#define CMD_GEN_HOST_ACK 0x80
+#define CMD_GEN_MPU_ACK 0x81
+#define CMD_GET_BOARD_TYPE 0x82
+#define CMD_SET_CONTROL 0x88
+#define CMD_GET_CONTROL 0x89
+#define CMD_SET_MT32 0x96
+#define CMD_GET_MT32 0x97
+#define CMD_SET_EXTMIDI 0x9b
+#define CMD_GET_EXTMIDI 0x9c
+
+#define CMD_ACK 0x80
+
+typedef struct sscape_info
+ {
+ int base, irq, dma;
+ int ok; /* Properly detected */
+ int dma_allocated;
+ int my_audiodev;
+ int opened;
+ }
+
+sscape_info;
+static struct sscape_info dev_info =
+{0};
+static struct sscape_info *devc = &dev_info;
+
+DEFINE_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag);
+
+#ifdef REVEAL_SPEA
+/* Spea and Reveal have assigned interrupt bits differently than Ensoniq */
+static char valid_interrupts[] =
+{9, 7, 5, 15};
+
+#else
+static char valid_interrupts[] =
+{9, 5, 7, 10};
+
+#endif
+
+static unsigned char
+sscape_read (struct sscape_info *devc, int reg)
+{
+ unsigned long flags;
+ unsigned char val;
+
+ DISABLE_INTR (flags);
+ OUTB (reg, PORT (ODIE_ADDR));
+ val = INB (PORT (ODIE_DATA));
+ RESTORE_INTR (flags);
+ return val;
+}
+
+static void
+sscape_write (struct sscape_info *devc, int reg, int data)
+{
+ unsigned long flags;
+
+ DISABLE_INTR (flags);
+ OUTB (reg, PORT (ODIE_ADDR));
+ OUTB (data, PORT (ODIE_DATA));
+ RESTORE_INTR (flags);
+}
+
+static void
+host_open (struct sscape_info *devc)
+{
+ OUTB (0x00, PORT (HOST_CTRL)); /* Put the board to the host mode */
+}
+
+static void
+host_close (struct sscape_info *devc)
+{
+ OUTB (0x03, PORT (HOST_CTRL)); /* Put the board to the MIDI mode */
+}
+
+static int
+host_write (struct sscape_info *devc, unsigned char *data, int count)
+{
+ unsigned long flags;
+ int i, timeout;
+
+ DISABLE_INTR (flags);
+
+ /*
+ * Send the command and data bytes
+ */
+
+ for (i = 0; i < count; i++)
+ {
+ for (timeout = 10000; timeout > 0; timeout--)
+ if (INB (PORT (HOST_CTRL)) & TX_READY)
+ break;
+
+ if (timeout <= 0)
+ {
+ RESTORE_INTR (flags);
+ return 0;
+ }
+
+ OUTB (data[i], PORT (HOST_DATA));
+ }
+
+
+ RESTORE_INTR (flags);
+
+ return 1;
+}
+
+static int
+host_read (struct sscape_info *devc)
+{
+ unsigned long flags;
+ int timeout;
+ unsigned char data;
+
+ DISABLE_INTR (flags);
+
+ /*
+ * Read a byte
+ */
+
+ for (timeout = 10000; timeout > 0; timeout--)
+ if (INB (PORT (HOST_CTRL)) & RX_READY)
+ break;
+
+ if (timeout <= 0)
+ {
+ RESTORE_INTR (flags);
+ return -1;
+ }
+
+ data = INB (PORT (HOST_DATA));
+
+ RESTORE_INTR (flags);
+
+ return data;
+}
+
+static int
+host_command1 (struct sscape_info *devc, int cmd)
+{
+ unsigned char buf[10];
+
+ buf[0] = (unsigned char) (cmd & 0xff);
+
+ return host_write (devc, buf, 1);
+}
+
+static int
+host_command2 (struct sscape_info *devc, int cmd, int parm1)
+{
+ unsigned char buf[10];
+
+ buf[0] = (unsigned char) (cmd & 0xff);
+ buf[1] = (unsigned char) (parm1 & 0xff);
+
+ return host_write (devc, buf, 2);
+}
+
+static int
+host_command3 (struct sscape_info *devc, int cmd, int parm1, int parm2)
+{
+ unsigned char buf[10];
+
+ buf[0] = (unsigned char) (cmd & 0xff);
+ buf[1] = (unsigned char) (parm1 & 0xff);
+ buf[2] = (unsigned char) (parm2 & 0xff);
+
+ return host_write (devc, buf, 3);
+}
+
+static void
+set_mt32 (struct sscape_info *devc, int value)
+{
+ host_open (devc);
+ host_command2 (devc, CMD_SET_MT32,
+ value ? 1 : 0);
+ if (host_read (devc) != CMD_ACK)
+ {
+ printk ("SNDSCAPE: Setting MT32 mode failed\n");
+ }
+ host_close (devc);
+}
+
+static int
+get_board_type (struct sscape_info *devc)
+{
+ int tmp;
+
+ host_open (devc);
+ if (!host_command1 (devc, CMD_GET_BOARD_TYPE))
+ tmp = -1;
+ else
+ tmp = host_read (devc);
+ host_close (devc);
+ return tmp;
+}
+
+void
+sscapeintr (INT_HANDLER_PARMS (irq, dummy))
+{
+ unsigned char bits, tmp;
+ static int debug = 0;
+
+ printk ("sscapeintr(0x%02x)\n", (bits = sscape_read (devc, GA_INTSTAT_REG)));
+ if (SOMEONE_WAITING (sscape_sleeper, sscape_sleep_flag))
+ {
+ WAKE_UP (sscape_sleeper, sscape_sleep_flag);
+ }
+
+ if (bits & 0x02) /* Host interface interrupt */
+ {
+ printk ("SSCAPE: Host interrupt, data=%02x\n", host_read (devc));
+ }
+
+#if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
+ if (bits & 0x01)
+ {
+ mpuintr (INT_HANDLER_CALL (irq));
+ if (debug++ > 10) /* Temporary debugging hack */
+ {
+ sscape_write (devc, GA_INTENA_REG, 0x00); /* Disable all interrupts */
+ }
+ }
+#endif
+
+ /*
+ * Acknowledge interrupts (toggle the interrupt bits)
+ */
+
+ tmp = sscape_read (devc, GA_INTENA_REG);
+ sscape_write (devc, GA_INTENA_REG, (~bits & 0x0e) | (tmp & 0xf1));
+
+}
+
+static void
+sscape_enable_intr (struct sscape_info *devc, unsigned intr_bits)
+{
+ unsigned char temp, orig;
+
+ temp = orig = sscape_read (devc, GA_INTENA_REG);
+ temp |= intr_bits;
+ temp |= 0x80; /* Master IRQ enable */
+
+ if (temp == orig)
+ return; /* No change */
+
+ sscape_write (devc, GA_INTENA_REG, temp);
+}
+
+static void
+sscape_disable_intr (struct sscape_info *devc, unsigned intr_bits)
+{
+ unsigned char temp, orig;
+
+ temp = orig = sscape_read (devc, GA_INTENA_REG);
+ temp &= ~intr_bits;
+ if ((temp & ~0x80) == 0x00)
+ temp = 0x00; /* Master IRQ disable */
+ if (temp == orig)
+ return; /* No change */
+
+ sscape_write (devc, GA_INTENA_REG, temp);
+}
+
+static void
+do_dma (struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size, int mode)
+{
+ unsigned char temp;
+
+ if (dma_chan != SSCAPE_DMA_A)
+ {
+ printk ("SSCAPE: Tried to use DMA channel != A. Why?\n");
+ return;
+ }
+
+ DMAbuf_start_dma (devc->my_audiodev,
+ buf,
+ blk_size, mode);
+
+ temp = devc->dma << 4; /* Setup DMA channel select bits */
+ if (devc->dma <= 3)
+ temp |= 0x80; /* 8 bit DMA channel */
+
+ temp |= 1; /* Trigger DMA */
+ sscape_write (devc, GA_DMAA_REG, temp);
+ temp &= 0xfe; /* Clear DMA trigger */
+ sscape_write (devc, GA_DMAA_REG, temp);
+}
+
+static int
+verify_mpu (struct sscape_info *devc)
+{
+ /*
+ * The SoundScape board could be in three modes (MPU, 8250 and host).
+ * If the card is not in the MPU mode, enabling the MPU driver will
+ * cause infinite loop (the driver believes that there is always some
+ * received data in the buffer.
+ *
+ * Detect this by looking if there are more than 10 received MIDI bytes
+ * (0x00) in the buffer.
+ */
+
+ int i;
+
+ for (i = 0; i < 10; i++)
+ {
+ if (INB (devc->base + HOST_CTRL) & 0x80)
+ return 1;
+
+ if (INB (devc->base) != 0x00)
+ return 1;
+ }
+
+ printk ("SoundScape: The device is not in the MPU-401 mode\n");
+ return 0;
+}
+
+static int
+sscape_coproc_open (void *dev_info, int sub_device)
+{
+ if (sub_device == COPR_MIDI)
+ {
+ set_mt32 (devc, 0);
+ if (!verify_mpu (devc))
+ return RET_ERROR (EIO);
+ }
+
+ return 0;
+}
+
+static void
+sscape_coproc_close (void *dev_info, int sub_device)
+{
+ struct sscape_info *devc = dev_info;
+ unsigned long flags;
+
+ DISABLE_INTR (flags);
+ if (devc->dma_allocated)
+ {
+ sscape_write (devc, GA_DMAA_REG, 0x20); /* DMA channel disabled */
+#ifndef EXCLUDE_NATIVE_PCM
+ DMAbuf_close_dma (devc->my_audiodev);
+#endif
+ devc->dma_allocated = 0;
+ }
+ RESET_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag);
+ RESTORE_INTR (flags);
+
+ return;
+}
+
+static void
+sscape_coproc_reset (void *dev_info)
+{
+}
+
+static int
+sscape_download_boot (struct sscape_info *devc, unsigned char *block, int size, int flag)
+{
+ unsigned long flags;
+ unsigned char temp;
+ int done, timeout;
+
+ if (flag & CPF_FIRST)
+ {
+ /*
+ * First block. Have to allocate DMA and to reset the board
+ * before continuing.
+ */
+
+ DISABLE_INTR (flags);
+ if (devc->dma_allocated == 0)
+ {
+#ifndef EXCLUDE_NATIVE_PCM
+ if (DMAbuf_open_dma (devc->my_audiodev) < 0)
+ {
+ RESTORE_INTR (flags);
+ return 0;
+ }
+#endif
+
+ devc->dma_allocated = 1;
+ }
+ RESTORE_INTR (flags);
+
+ sscape_write (devc, GA_HMCTL_REG,
+ (temp = sscape_read (devc, GA_HMCTL_REG)) & 0x3f); /*Reset */
+
+ for (timeout = 10000; timeout > 0; timeout--)
+ sscape_read (devc, GA_HMCTL_REG); /* Delay */
+
+ /* Take board out of reset */
+ sscape_write (devc, GA_HMCTL_REG,
+ (temp = sscape_read (devc, GA_HMCTL_REG)) | 0x80);
+ }
+
+ /*
+ * Transfer one code block using DMA
+ */
+ memcpy (audio_devs[devc->my_audiodev]->dmap->raw_buf[0], block, size);
+
+ DISABLE_INTR (flags);
+/******** INTERRUPTS DISABLED NOW ********/
+ do_dma (devc, SSCAPE_DMA_A,
+ audio_devs[devc->my_audiodev]->dmap->raw_buf_phys[0],
+ size, DMA_MODE_WRITE);
+
+ /*
+ * Wait until transfer completes.
+ */
+ RESET_WAIT_QUEUE (sscape_sleeper, sscape_sleep_flag);
+ done = 0;
+ timeout = 100;
+ while (!done && timeout-- > 0)
+ {
+ int resid;
+
+ DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1);
+ clear_dma_ff (devc->dma);
+ if ((resid = get_dma_residue (devc->dma)) == 0)
+ done = 1;
+ }
+
+ RESTORE_INTR (flags);
+ if (!done)
+ return 0;
+
+ if (flag & CPF_LAST)
+ {
+ /*
+ * Take the board out of reset
+ */
+ OUTB (0x00, PORT (HOST_CTRL));
+ OUTB (0x00, PORT (MIDI_CTRL));
+
+ temp = sscape_read (devc, GA_HMCTL_REG);
+ temp |= 0x40;
+ sscape_write (devc, GA_HMCTL_REG, temp); /* Kickstart the board */
+
+ /*
+ * Wait until the ODB wakes up
+ */
+
+ DISABLE_INTR (flags);
+ done = 0;
+ timeout = 5 * HZ;
+ while (!done && timeout-- > 0)
+ {
+ DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1);
+ if (INB (PORT (HOST_DATA)) == 0xff) /* OBP startup acknowledge */
+ done = 1;
+ }
+ RESTORE_INTR (flags);
+ if (!done)
+ {
+ printk ("SoundScape: The OBP didn't respond after code download\n");
+ return 0;
+ }
+
+ DISABLE_INTR (flags);
+ done = 0;
+ timeout = 5 * HZ;
+ while (!done && timeout-- > 0)
+ {
+ DO_SLEEP (sscape_sleeper, sscape_sleep_flag, 1);
+ if (INB (PORT (HOST_DATA)) == 0xfe) /* Host startup acknowledge */
+ done = 1;
+ }
+ RESTORE_INTR (flags);
+ if (!done)
+ {
+ printk ("SoundScape: OBP Initialization failed.\n");
+ return 0;
+ }
+
+ printk ("SoundScape board of type %d initialized OK\n",
+ get_board_type (devc));
+
+#ifdef SSCAPE_DEBUG3
+ /*
+ * Temporary debugging aid. Print contents of the registers after
+ * downloading the code.
+ */
+ {
+ int i;
+
+ for (i = 0; i < 13; i++)
+ printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i));
+ }
+#endif
+
+ }
+
+ return 1;
+}
+
+static int
+download_boot_block (void *dev_info, copr_buffer * buf)
+{
+ if (buf->len <= 0 || buf->len > sizeof (buf->data))
+ return RET_ERROR (EINVAL);
+
+ if (!sscape_download_boot (devc, buf->data, buf->len, buf->flags))
+ {
+ printk ("SSCAPE: Unable to load microcode block to the OBP.\n");
+ return RET_ERROR (EIO);
+ }
+
+ return 0;
+}
+
+static int
+sscape_coproc_ioctl (void *dev_info, unsigned int cmd, unsigned int arg, int local)
+{
+
+ switch (cmd)
+ {
+ case SNDCTL_COPR_RESET:
+ sscape_coproc_reset (dev_info);
+ return 0;
+ break;
+
+ case SNDCTL_COPR_LOAD:
+ {
+ copr_buffer *buf;
+ int err;
+
+ buf = (copr_buffer *) KERNEL_MALLOC (sizeof (copr_buffer));
+ IOCTL_FROM_USER ((char *) buf, (char *) arg, 0, sizeof (*buf));
+ err = download_boot_block (dev_info, buf);
+ KERNEL_FREE (buf);
+ return err;
+ }
+ break;
+
+ default:
+ return RET_ERROR (EINVAL);
+ }
+
+ return RET_ERROR (EINVAL);
+}
+
+static coproc_operations sscape_coproc_operations =
+{
+ "SoundScape M68K",
+ sscape_coproc_open,
+ sscape_coproc_close,
+ sscape_coproc_ioctl,
+ sscape_coproc_reset,
+ &dev_info
+};
+
+static int
+sscape_audio_open (int dev, int mode)
+{
+ unsigned long flags;
+ sscape_info *devc = (sscape_info *) audio_devs[dev]->devc;
+
+ DISABLE_INTR (flags);
+ if (devc->opened)
+ {
+ RESTORE_INTR (flags);
+ return RET_ERROR (EBUSY);
+ }
+
+ if (devc->dma_allocated == 0)
+ {
+ int err;
+
+ if ((err = DMAbuf_open_dma (devc->my_audiodev)) < 0)
+ {
+ RESTORE_INTR (flags);
+ return err;
+ }
+
+ devc->dma_allocated = 1;
+ }
+
+ devc->opened = 1;
+ RESTORE_INTR (flags);
+#ifdef SSCAPE_DEBUG4
+ /*
+ * Temporary debugging aid. Print contents of the registers
+ * when the device is opened.
+ */
+ {
+ int i;
+
+ for (i = 0; i < 13; i++)
+ printk ("I%d = %02x\n", i, sscape_read (devc, i));
+ }
+#endif
+
+ return 0;
+}
+
+static void
+sscape_audio_close (int dev)
+{
+ unsigned long flags;
+ sscape_info *devc = (sscape_info *) audio_devs[dev]->devc;
+
+ DEB (printk ("sscape_audio_close(void)\n"));
+
+ DISABLE_INTR (flags);
+
+ if (devc->dma_allocated)
+ {
+ sscape_write (devc, GA_DMAA_REG, 0x20); /* DMA channel disabled */
+ DMAbuf_close_dma (dev);
+ devc->dma_allocated = 0;
+ }
+ devc->opened = 0;
+
+ RESTORE_INTR (flags);
+}
+
+static int
+set_speed (sscape_info * devc, int arg)
+{
+ return 8000;
+}
+
+static int
+set_channels (sscape_info * devc, int arg)
+{
+ return 1;
+}
+
+static int
+set_format (sscape_info * devc, int arg)
+{
+ return AFMT_U8;
+}
+
+static int
+sscape_audio_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
+{
+ sscape_info *devc = (sscape_info *) audio_devs[dev]->devc;
+
+ switch (cmd)
+ {
+ case SOUND_PCM_WRITE_RATE:
+ if (local)
+ return set_speed (devc, arg);
+ return IOCTL_OUT (arg, set_speed (devc, IOCTL_IN (arg)));
+
+ case SOUND_PCM_READ_RATE:
+ if (local)
+ return 8000;
+ return IOCTL_OUT (arg, 8000);
+
+ case SNDCTL_DSP_STEREO:
+ if (local)
+ return set_channels (devc, arg + 1) - 1;
+ return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg) + 1) - 1);
+
+ case SOUND_PCM_WRITE_CHANNELS:
+ if (local)
+ return set_channels (devc, arg);
+ return IOCTL_OUT (arg, set_channels (devc, IOCTL_IN (arg)));
+
+ case SOUND_PCM_READ_CHANNELS:
+ if (local)
+ return 1;
+ return IOCTL_OUT (arg, 1);
+
+ case SNDCTL_DSP_SAMPLESIZE:
+ if (local)
+ return set_format (devc, arg);
+ return IOCTL_OUT (arg, set_format (devc, IOCTL_IN (arg)));
+
+ case SOUND_PCM_READ_BITS:
+ if (local)
+ return 8;
+ return IOCTL_OUT (arg, 8);
+
+ default:;
+ }
+ return RET_ERROR (EINVAL);
+}
+
+static void
+sscape_audio_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
+{
+}
+
+static void
+sscape_audio_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
+{
+}
+
+static int
+sscape_audio_prepare_for_input (int dev, int bsize, int bcount)
+{
+ return 0;
+}
+
+static int
+sscape_audio_prepare_for_output (int dev, int bsize, int bcount)
+{
+ return 0;
+}
+
+static void
+sscape_audio_halt (int dev)
+{
+}
+
+static void
+sscape_audio_reset (int dev)
+{
+ sscape_audio_halt (dev);
+}
+
+static struct audio_operations sscape_audio_operations =
+{
+ "Ensoniq SoundScape channel A",
+ 0,
+ AFMT_U8 | AFMT_S16_LE,
+ NULL,
+ sscape_audio_open,
+ sscape_audio_close,
+ sscape_audio_output_block,
+ sscape_audio_start_input,
+ sscape_audio_ioctl,
+ sscape_audio_prepare_for_input,
+ sscape_audio_prepare_for_output,
+ sscape_audio_reset,
+ sscape_audio_halt,
+ NULL,
+ NULL
+};
+
+long
+attach_sscape (long mem_start, struct address_info *hw_config)
+{
+ int my_dev;
+
+#ifndef SSCAPE_REGS
+ /*
+ * Config register values for Spea/V7 Media FX and Ensoniq S-2000.
+ * These values are card
+ * dependent. If you have another SoundScape based card, you have to
+ * find the correct values. Do the following:
+ * - Compile this driver with SSCAPE_DEBUG1 defined.
+ * - Shut down and power off your machine.
+ * - Boot with DOS so that the SSINIT.EXE program is run.
+ * - Warm boot to {Linux|SYSV|BSD} and write down the lines displayed
+ * when detecting the SoundScape.
+ * - Modify the following list to use the values printed during boot.
+ * Undefine the SSCAPE_DEBUG1
+ */
+#define SSCAPE_REGS { \
+/* I0 */ 0x00, \
+ 0xf0, /* Note! Ignored. Set always to 0xf0 */ \
+ 0x20, /* Note! Ignored. Set always to 0x20 */ \
+ 0x20, /* Note! Ignored. Set always to 0x20 */ \
+ 0xf5, /* Ignored */ \
+ 0x10, \
+ 0x00, \
+ 0x2e, /* I7 MEM config A. Likely to vary between models */ \
+ 0x00, /* I8 MEM config A. Likely to vary between models */ \
+/* I9 */ 0x40 /* Ignored */ \
+ }
+#endif
+
+ unsigned long flags;
+ static unsigned char regs[10] = SSCAPE_REGS;
+
+ int i, irq_bits = 0xff;
+
+ if (!probe_sscape (hw_config))
+ return mem_start;
+
+ printk (" <Ensoniq Soundscape>");
+
+ for (i = 0; i < sizeof (valid_interrupts); i++)
+ if (hw_config->irq == valid_interrupts[i])
+ {
+ irq_bits = i;
+ break;
+ }
+
+ if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff))
+ {
+ printk ("Invalid IRQ%d\n", hw_config->irq);
+ return mem_start;
+ }
+
+ DISABLE_INTR (flags);
+
+ for (i = 1; i < 10; i++)
+ switch (i)
+ {
+ case 1: /* Host interrupt enable */
+ sscape_write (devc, i, 0xf0); /* All interrupts enabled */
+ break;
+
+ case 2: /* DMA A status/trigger register */
+ case 3: /* DMA B status/trigger register */
+ sscape_write (devc, i, 0x20); /* DMA channel disabled */
+ break;
+
+ case 4: /* Host interrupt config reg */
+ sscape_write (devc, i, 0xf0 | (irq_bits << 2) | irq_bits);
+ break;
+
+ case 5: /* Don't destroy CD-ROM DMA config bits (0xc0) */
+ sscape_write (devc, i, (regs[i] & 0x3f) |
+ (sscape_read (devc, i) & 0x0c));
+ break;
+
+ case 6: /* CD-ROM config. Don't touch. */
+ break;
+
+ case 9: /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
+ sscape_write (devc, i,
+ (sscape_read (devc, i) & 0xf0) | 0x00);
+ break;
+
+ default:
+ sscape_write (devc, i, regs[i]);
+ }
+
+ RESTORE_INTR (flags);
+
+#ifdef SSCAPE_DEBUG2
+ /*
+ * Temporary debugging aid. Print contents of the registers after
+ * changing them.
+ */
+ {
+ int i;
+
+ for (i = 0; i < 13; i++)
+ printk ("I%d = %02x (new value)\n", i, sscape_read (devc, i));
+ }
+#endif
+
+#if !defined(EXCLUDE_MIDI) && !defined(EXCLUDE_MPU_EMU)
+ hw_config->always_detect = 1;
+ if (probe_mpu401 (hw_config))
+ {
+ int prev_devs;
+
+ prev_devs = num_midis;
+ mem_start = attach_mpu401 (mem_start, hw_config);
+
+ if (num_midis == (prev_devs + 1)) /* The MPU driver installed itself */
+ midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
+ }
+#endif
+
+#ifndef EXCLUDE_NATIVE_PCM
+ /* Not supported yet */
+
+#ifndef EXCLUDE_AUDIO
+ if (num_audiodevs < MAX_AUDIO_DEV)
+ {
+ audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations;
+ audio_devs[my_dev]->dmachan = hw_config->dma;
+ audio_devs[my_dev]->buffcount = 1;
+ audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
+ audio_devs[my_dev]->devc = devc;
+ devc->my_audiodev = my_dev;
+ devc->opened = 0;
+ audio_devs[my_dev]->coproc = &sscape_coproc_operations;
+ if (snd_set_irq_handler (hw_config->irq, sscapeintr, "SoundScape") < 0)
+ printk ("Error: Can't allocate IRQ for SoundScape\n");
+
+ sscape_write (devc, GA_INTENA_REG, 0x80); /* Master IRQ enable */
+ }
+ else
+ printk ("SoundScape: More than enough audio devices detected\n");
+#endif
+#endif
+ devc->ok = 1;
+ return mem_start;
+}
+
+int
+probe_sscape (struct address_info *hw_config)
+{
+ unsigned char save;
+
+ devc->base = hw_config->io_base;
+ devc->irq = hw_config->irq;
+ devc->dma = hw_config->dma;
+
+ /*
+ * First check that the address register of "ODIE" is
+ * there and that it has exactly 4 writeable bits.
+ * First 4 bits
+ */
+ if ((save = INB (PORT (ODIE_ADDR))) & 0xf0)
+ return 0;
+
+ OUTB (0x00, PORT (ODIE_ADDR));
+ if (INB (PORT (ODIE_ADDR)) != 0x00)
+ return 0;
+
+ OUTB (0xff, PORT (ODIE_ADDR));
+ if (INB (PORT (ODIE_ADDR)) != 0x0f)
+ return 0;
+
+ OUTB (save, PORT (ODIE_ADDR));
+
+ /*
+ * Now verify that some indirect registers return zero on some bits.
+ * This may break the driver with some future revisions of "ODIE" but...
+ */
+
+ if (sscape_read (devc, 0) & 0x0c)
+ return 0;
+
+ if (sscape_read (devc, 1) & 0x0f)
+ return 0;
+
+ if (sscape_read (devc, 5) & 0x0f)
+ return 0;
+
+#ifdef SSCAPE_DEBUG1
+ /*
+ * Temporary debugging aid. Print contents of the registers before
+ * changing them.
+ */
+ {
+ int i;
+
+ for (i = 0; i < 13; i++)
+ printk ("I%d = %02x (old value)\n", i, sscape_read (devc, i));
+ }
+#endif
+
+ return 1;
+}
+
+int
+probe_ss_ms_sound (struct address_info *hw_config)
+{
+ int i, irq_bits = 0xff;
+
+ if (devc->ok == 0)
+ {
+ printk ("SoundScape: Invalid initialization order.\n");
+ return 0;
+ }
+
+ for (i = 0; i < sizeof (valid_interrupts); i++)
+ if (hw_config->irq == valid_interrupts[i])
+ {
+ irq_bits = i;
+ break;
+ }
+#ifdef REVEAL_SPEA
+ {
+ int tmp, status = 0;
+ int cc;
+
+ if (!((tmp = sscape_read (devc, GA_HMCTL_REG)) & 0xc0))
+ {
+ sscape_write (devc, GA_HMCTL_REG, tmp | 0x80);
+ for (cc = 0; cc < 200000; ++cc)
+ INB (devc->base + ODIE_ADDR);
+ }
+ }
+#endif
+
+ if (hw_config->irq > 15 || irq_bits == 0xff)
+ {
+ printk ("SoundScape: Invalid MSS IRQ%d\n", hw_config->irq);
+ return 0;
+ }
+
+ return ad1848_detect (hw_config->io_base);
+}
+
+long
+attach_ss_ms_sound (long mem_start, struct address_info *hw_config)
+{
+ /*
+ * This routine configures the SoundScape card for use with the
+ * Win Sound System driver. The AD1848 codec interface uses the CD-ROM
+ * config registers of the "ODIE".
+ */
+
+ int i, irq_bits = 0xff;
+
+#ifdef EXCLUDE_NATIVE_PCM
+ int prev_devs = num_audiodevs;
+
+#endif
+
+ /*
+ * Setup the DMA polarity.
+ */
+ sscape_write (devc, GA_DMACFG_REG, 0x50);
+
+ /*
+ * Take the gate-arry off of the DMA channel.
+ */
+ sscape_write (devc, GA_DMAB_REG, 0x20);
+
+ /*
+ * Init the AD1848 (CD-ROM) config reg.
+ */
+
+ for (i = 0; i < sizeof (valid_interrupts); i++)
+ if (hw_config->irq == valid_interrupts[i])
+ {
+ irq_bits = i;
+ break;
+ }
+
+ sscape_write (devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) |
+ (irq_bits << 1));
+
+ if (hw_config->irq == devc->irq)
+ printk ("SoundScape: Warning! The WSS mode can't share IRQ with MIDI\n");
+
+ ad1848_init ("SoundScape", hw_config->io_base,
+ hw_config->irq,
+ hw_config->dma,
+ hw_config->dma);
+
+#ifdef EXCLUDE_NATIVE_PCM
+ if (num_audiodevs == (prev_devs + 1)) /* The AD1848 driver installed itself */
+ audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
+#endif
+#ifdef SSCAPE_DEBUG5
+ /*
+ * Temporary debugging aid. Print contents of the registers
+ * after the AD1848 device has been initialized.
+ */
+ {
+ int i;
+
+ for (i = 0; i < 13; i++)
+ printk ("I%d = %02x\n", i, sscape_read (devc, i));
+ }
+#endif
+
+ return mem_start;
+}
+
+#endif
diff --git a/sys/i386/isa/sound/trix.c b/sys/i386/isa/sound/trix.c
new file mode 100644
index 0000000000000..6e3db0fa7c901
--- /dev/null
+++ b/sys/i386/isa/sound/trix.c
@@ -0,0 +1,323 @@
+/*
+ * sound/trix.c
+ *
+ * Low level driver for the MediaTriX AudioTriX Pro
+ * (MT-0002-PC Control Chip)
+ *
+ * Copyright by Hannu Savolainen 1995
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "sound_config.h"
+
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_TRIX)
+
+#ifdef INCLUDE_TRIX_BOOT
+#include "trix_boot.h"
+#endif
+
+static int kilroy_was_here = 0; /* Don't detect twice */
+static int sb_initialized = 0;
+static int mpu_initialized = 0;
+
+static unsigned char
+trix_read (int addr)
+{
+ OUTB ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */
+ return INB (0x391); /* MT-0002-PC ASIC data */
+}
+
+static void
+trix_write (int addr, int data)
+{
+ OUTB ((unsigned char) addr, 0x390); /* MT-0002-PC ASIC address */
+ OUTB ((unsigned char) data, 0x391); /* MT-0002-PC ASIC data */
+}
+
+static void
+download_boot (int base)
+{
+ int i = 0, n = sizeof (trix_boot);
+
+ trix_write (0xf8, 0x00); /* ??????? */
+ OUTB (0x01, base + 6); /* Clear the internal data pointer */
+ OUTB (0x00, base + 6); /* Restart */
+
+ /*
+ * Write the boot code to the RAM upload/download register.
+ * Each write increments the internal data pointer.
+ */
+ OUTB (0x01, base + 6); /* Clear the internal data pointer */
+ OUTB (0x1A, 0x390); /* Select RAM download/upload port */
+
+ for (i = 0; i < n; i++)
+ OUTB (trix_boot[i], 0x391);
+ for (i = n; i < 10016; i++) /* Clear up to first 16 bytes of data RAM */
+ OUTB (0x00, 0x391);
+ OUTB (0x00, base + 6); /* Reset */
+ OUTB (0x50, 0x390); /* ?????? */
+}
+
+static int
+trix_set_wss_port (struct address_info *hw_config)
+{
+ unsigned char addr_bits;
+
+ if (kilroy_was_here) /* Already initialized */
+ return 0;
+
+ kilroy_was_here = 1;
+
+ if (trix_read (0x15) != 0x71) /* No asic signature */
+ return 0;
+
+ /*
+ * Disable separate wave playback and recording DMA channels since
+ * the driver doesn't support duplex mode yet.
+ */
+
+ trix_write (0x13, trix_read (0x13) & ~0x80);
+ trix_write (0x14, trix_read (0x14) & ~0x80);
+
+ /*
+ * Configure the ASIC to place the codec to the proper I/O location
+ */
+
+ switch (hw_config->io_base)
+ {
+ case 0x530:
+ addr_bits = 0;
+ break;
+ case 0x604:
+ addr_bits = 1;
+ break;
+ case 0xE80:
+ addr_bits = 2;
+ break;
+ case 0xF40:
+ addr_bits = 3;
+ break;
+ default:
+ return 0;
+ }
+
+ trix_write (0x19, (trix_read (0x19) & 0x03) | addr_bits);
+ return 1;
+}
+
+/*
+ * Probe and attach routines for the Windows Sound System mode of
+ * AudioTriX Pro
+ */
+
+int
+probe_trix_wss (struct address_info *hw_config)
+{
+ /*
+ * Check if the IO port returns valid signature. The original MS Sound
+ * system returns 0x04 while some cards (AudioTriX Pro for example)
+ * return 0x00.
+ */
+ if (!trix_set_wss_port (hw_config))
+ return 0;
+
+ if ((INB (hw_config->io_base + 3) & 0x3f) != 0x00)
+ {
+ DDB (printk ("No MSS signature detected on port 0x%x\n", hw_config->io_base));
+ return 0;
+ }
+
+ if (hw_config->irq > 11)
+ {
+ printk ("AudioTriX: Bad WSS IRQ %d\n", hw_config->irq);
+ return 0;
+ }
+
+ if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
+ {
+ printk ("AudioTriX: Bad WSS DMA %d\n", hw_config->dma);
+ return 0;
+ }
+
+ /*
+ * Check that DMA0 is not in use with a 8 bit board.
+ */
+
+ if (hw_config->dma == 0 && INB (hw_config->io_base + 3) & 0x80)
+ {
+ printk ("AudioTriX: Can't use DMA0 with a 8 bit card\n");
+ return 0;
+ }
+
+ if (hw_config->irq > 7 && hw_config->irq != 9 && INB (hw_config->io_base + 3) & 0x80)
+ {
+ printk ("AudioTriX: Can't use IRQ%d with a 8 bit card\n", hw_config->irq);
+ return 0;
+ }
+
+ return ad1848_detect (hw_config->io_base + 4);
+}
+
+long
+attach_trix_wss (long mem_start, struct address_info *hw_config)
+{
+ static unsigned char interrupt_bits[12] =
+ {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20};
+ char bits;
+
+ static unsigned char dma_bits[4] =
+ {1, 2, 0, 3};
+
+ int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
+
+ if (!kilroy_was_here)
+ return mem_start;
+
+ /*
+ * Set the IRQ and DMA addresses.
+ */
+
+ bits = interrupt_bits[hw_config->irq];
+ if (bits == -1)
+ return mem_start;
+
+ OUTB (bits | 0x40, config_port);
+ if ((INB (version_port) & 0x40) == 0)
+ printk ("[IRQ Conflict?]");
+
+ OUTB (bits | dma_bits[hw_config->dma], config_port); /* Write IRQ+DMA setup */
+
+ ad1848_init ("AudioTriX Pro", hw_config->io_base + 4,
+ hw_config->irq,
+ hw_config->dma,
+ hw_config->dma);
+ return mem_start;
+}
+
+int
+probe_trix_sb (struct address_info *hw_config)
+{
+
+ int tmp;
+ unsigned char conf;
+ static char irq_translate[] =
+ {-1, -1, -1, 0, 1, 2, -1, 3};
+
+#ifndef INCLUDE_TRIX_BOOT
+ return 0; /* No boot code -> no fun */
+#endif
+ if (!kilroy_was_here)
+ return 0; /* AudioTriX Pro has not been detected earlier */
+
+ if (sb_initialized)
+ return 0;
+
+ if (hw_config->io_base & 0xffffff8f != 0x200)
+ return 0;
+
+ tmp = hw_config->irq;
+ if (tmp > 7)
+ return 0;
+ if (irq_translate[tmp] == -1)
+ return 0;
+
+ tmp = hw_config->dma;
+ if (tmp != 1 && tmp != 3)
+ return 0;
+
+ conf = 0x84; /* DMA and IRQ enable */
+ conf |= hw_config->io_base & 0x70; /* I/O address bits */
+ conf |= irq_translate[hw_config->irq];
+ if (hw_config->dma == 3)
+ conf |= 0x08;
+ trix_write (0x1b, conf);
+
+ download_boot (hw_config->io_base);
+ sb_initialized = 1;
+
+ return 1;
+}
+
+long
+attach_trix_sb (long mem_start, struct address_info *hw_config)
+{
+ printk (" <AudioTriX>");
+ return mem_start;
+}
+
+long
+attach_trix_mpu (long mem_start, struct address_info *hw_config)
+{
+ return attach_mpu401 (mem_start, hw_config);
+}
+
+int
+probe_trix_mpu (struct address_info *hw_config)
+{
+ unsigned char conf;
+ static char irq_bits[] =
+ {-1, -1, -1, 1, 2, 3, -1, 4, -1, 5};
+
+ if (!kilroy_was_here)
+ return 0; /* AudioTriX Pro has not been detected earlier */
+
+ if (!sb_initialized)
+ return 0;
+
+ if (mpu_initialized)
+ return 0;
+
+ if (hw_config->irq > 9)
+ return 0;
+
+ if (irq_bits[hw_config->irq] == -1)
+ return 0;
+
+ switch (hw_config->io_base)
+ {
+ case 0x330:
+ conf = 0x00;
+ break;
+ case 0x370:
+ conf = 0x04;
+ break;
+ case 0x3b0:
+ conf = 0x08;
+ break;
+ case 0x3f0:
+ conf = 0x0c;
+ break;
+ default:
+ return 0; /* Invalid port */
+ }
+
+ conf |= irq_bits[hw_config->irq] << 4;
+
+ trix_write (0x19, (trix_read (0x19) & 0x83) | conf);
+
+ mpu_initialized = 1;
+
+ return probe_mpu401 (hw_config);
+}
+
+#endif
diff --git a/sys/i386/linux/imgact_linux.c b/sys/i386/linux/imgact_linux.c
new file mode 100644
index 0000000000000..d9650d3150ecc
--- /dev/null
+++ b/sys/i386/linux/imgact_linux.c
@@ -0,0 +1,235 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Based heavily on /sys/kern/imgact_aout.c which is:
+ * Copyright (c) 1993, David Greenman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: imgact_linux.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/resourcevar.h>
+#include <sys/exec.h>
+#include <sys/mman.h>
+#include <sys/imgact.h>
+#include <sys/imgact_aout.h>
+#include <sys/kernel.h>
+#include <sys/sysent.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+int
+exec_linux_imgact(iparams)
+ struct image_params *iparams;
+{
+ struct exec *a_out = (struct exec *) iparams->image_header;
+ struct vmspace *vmspace = iparams->proc->p_vmspace;
+ unsigned long vmaddr, virtual_offset, file_offset;
+ unsigned long buffer, bss_size;
+ int error;
+ extern struct sysentvec linux_sysvec;
+
+ if (((a_out->a_magic >> 16) & 0xff) != 0x64)
+ return -1;
+
+ /*
+ * Set file/virtual offset based on a.out variant.
+ */
+ switch ((int)(a_out->a_magic & 0xffff)) {
+ case 0413:
+ virtual_offset = 0;
+ file_offset = 1024;
+ break;
+ case 0314:
+ virtual_offset = 4096;
+ file_offset = 0;
+ break;
+ default:
+ return (-1);
+ }
+ bss_size = round_page(a_out->a_bss);
+
+ /*
+ * Check various fields in header for validity/bounds.
+ */
+ if (a_out->a_entry < virtual_offset ||
+ a_out->a_entry >= virtual_offset + a_out->a_text ||
+ a_out->a_text % NBPG || a_out->a_data % NBPG)
+ return (-1);
+
+ /* text + data can't exceed file size */
+ if (a_out->a_data + a_out->a_text > iparams->attr->va_size)
+ return (EFAULT);
+ /*
+ * text/data/bss must not exceed limits
+ */
+ if (a_out->a_text > MAXTSIZ || a_out->a_data + bss_size > MAXDSIZ ||
+ a_out->a_data+bss_size > iparams->proc->p_rlimit[RLIMIT_DATA].rlim_cur)
+ return (ENOMEM);
+
+ /* copy in arguments and/or environment from old process */
+ error = exec_extract_strings(iparams);
+ if (error)
+ return (error);
+
+ /*
+ * Destroy old process VM and create a new one (with a new stack)
+ */
+ exec_new_vmspace(iparams);
+
+ /*
+ * Check if file_offset page aligned,.
+ * Currently we cannot handle misalinged file offsets,
+ * and so we read in the entire image (what a waste).
+ */
+ if (file_offset & PGOFSET) {
+#ifdef DEBUG
+ printf("imgact: Non page aligned binary %d\n", file_offset);
+#endif
+ /*
+ * Map text read/execute
+ */
+ vmaddr = virtual_offset;
+ error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
+ round_page(a_out->a_text), FALSE);
+ if (error)
+ return error;
+
+ error = vm_mmap(kernel_map, &buffer,
+ round_page(a_out->a_text + file_offset),
+ VM_PROT_READ, VM_PROT_READ, MAP_FILE,
+ (caddr_t) iparams->vnodep, trunc_page(file_offset));
+ if (error)
+ return error;
+
+ error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr,
+ a_out->a_text);
+ if (error)
+ return error;
+
+ vm_map_remove(kernel_map, trunc_page(vmaddr),
+ round_page(a_out->a_text + file_offset));
+
+ error = vm_map_protect(&vmspace->vm_map, vmaddr,
+ round_page(a_out->a_text),
+ VM_PROT_EXECUTE|VM_PROT_READ, TRUE);
+ if (error)
+ return error;
+ /*
+ * Map data read/write
+ */
+ vmaddr = virtual_offset + a_out->a_text;
+ error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
+ round_page(a_out->a_data + bss_size), FALSE);
+ if (error)
+ return error;
+
+ error = vm_mmap(kernel_map, &buffer,
+ round_page(a_out->a_data + file_offset),
+ VM_PROT_READ, VM_PROT_READ, MAP_FILE,
+ (caddr_t) iparams->vnodep,
+ trunc_page(a_out->a_text + file_offset));
+ if (error)
+ return error;
+
+ error = copyout((caddr_t)(buffer + file_offset),
+ (caddr_t)vmaddr,
+ a_out->a_data);
+ if (error)
+ return error;
+
+ vm_map_remove(kernel_map, trunc_page(vmaddr),
+ round_page(a_out->a_data + file_offset));
+
+ error = vm_map_protect(&vmspace->vm_map, vmaddr,
+ round_page(a_out->a_data + bss_size),
+ VM_PROT_WRITE|VM_PROT_READ, TRUE);
+ if (error)
+ return error;
+ }
+ else {
+#ifdef DEBUG
+ printf("imgact: Page aligned binary %d\n", file_offset);
+#endif
+ /*
+ * Map text read/execute
+ */
+ vmaddr = virtual_offset;
+ error = vm_mmap(&vmspace->vm_map, &vmaddr, a_out->a_text,
+ VM_PROT_READ | VM_PROT_EXECUTE,
+ VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED,
+ (caddr_t)iparams->vnodep, file_offset);
+ if (error)
+ return (error);
+
+ /*
+ * Map data read/write
+ */
+ vmaddr = virtual_offset + a_out->a_text;
+ error = vm_mmap(&vmspace->vm_map, &vmaddr, a_out->a_data,
+ VM_PROT_READ | VM_PROT_WRITE,
+ VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED,
+ (caddr_t)iparams->vnodep, file_offset + a_out->a_text);
+ if (error)
+ return (error);
+
+ /*
+ * Allocate demand-zeroed area for uninitialized data
+ */
+ if (bss_size != 0) {
+ vmaddr = virtual_offset + a_out->a_text + a_out->a_data;
+ error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
+ bss_size, FALSE);
+ if (error)
+ return (error);
+ }
+ }
+ /* Fill in process VM information */
+ vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT;
+ vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT;
+ vmspace->vm_taddr = (caddr_t)virtual_offset;
+ vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text;
+
+ /* Fill in image_params */
+ iparams->interpreted = 0;
+ iparams->entry_addr = a_out->a_entry;
+
+ iparams->proc->p_sysent = &linux_sysvec;
+ return (0);
+}
+
+/*
+ * Tell kern_execve.c about it, with a little help from the linker.
+ * Since `const' objects end up in the text segment, TEXT_SET is the
+ * correct directive to use.
+ */
+const struct execsw linux_execsw = { exec_linux_imgact, "linux" };
+TEXT_SET(execsw_set, linux_execsw);
+
diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h
new file mode 100644
index 0000000000000..9d13bd156057d
--- /dev/null
+++ b/sys/i386/linux/linux.h
@@ -0,0 +1,406 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux.h,v 1.3 1995/06/08 13:50:52 sos Exp $
+ */
+
+#ifndef LINUX_H
+#define LINUX_H
+
+typedef unsigned short linux_uid_t;
+typedef unsigned short linux_gid_t;
+typedef unsigned short linux_dev_t;
+typedef unsigned long linux_ino_t;
+typedef unsigned short linux_mode_t;
+typedef unsigned short linux_nlink_t;
+typedef long linux_time_t;
+typedef long linux_clock_t;
+typedef char * linux_caddr_t;
+typedef long linux_off_t;
+typedef struct {
+ long val[2];
+} linux_fsid_t;
+typedef int linux_pid_t;
+typedef unsigned long linux_sigset_t;
+typedef void (*linux_handler_t)(int);
+typedef struct {
+ void (*sa_handler)(int);
+ linux_sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+} linux_sigaction_t;
+typedef int linux_key_t;
+
+extern int bsd_to_linux_signal[];
+extern int linux_to_bsd_signal[];
+
+/* misc defines */
+#define LINUX_NAME_MAX 255
+
+/* signal numbers */
+#define LINUX_SIGHUP 1
+#define LINUX_SIGINT 2
+#define LINUX_SIGQUIT 3
+#define LINUX_SIGILL 4
+#define LINUX_SIGTRAP 5
+#define LINUX_SIGABRT 6
+#define LINUX_SIGIOT 6
+#define LINUX_SIGUNUSED 7
+#define LINUX_SIGFPE 8
+#define LINUX_SIGKILL 9
+#define LINUX_SIGUSR1 10
+#define LINUX_SIGSEGV 11
+#define LINUX_SIGUSR2 12
+#define LINUX_SIGPIPE 13
+#define LINUX_SIGALRM 14
+#define LINUX_SIGTERM 15
+#define LINUX_SIGSTKFLT 16
+#define LINUX_SIGCHLD 17
+#define LINUX_SIGCONT 18
+#define LINUX_SIGSTOP 19
+#define LINUX_SIGTSTP 20
+#define LINUX_SIGTTIN 21
+#define LINUX_SIGTTOU 22
+#define LINUX_SIGIO 23
+#define LINUX_SIGPOLL LINUX_SIGIO
+#define LINUX_SIGURG LINUX_SIGIO
+#define LINUX_SIGXCPU 24
+#define LINUX_SIGXFSZ 25
+#define LINUX_SIGVTALRM 26
+#define LINUX_SIGPROF 27
+#define LINUX_SIGWINCH 28
+#define LINUX_SIGLOST 29
+#define LINUX_SIGPWR 30
+#define LINUX_SIGBUS LINUX_SIGUNUSED
+#define LINUX_NSIG 32
+
+/* sigaction flags */
+#define LINUX_SA_NOCLDSTOP 0x00000001
+#define LINUX_SA_ONSTACK 0x08000000
+#define LINUX_SA_RESTART 0x10000000
+#define LINUX_SA_INTERRUPT 0x20000000
+#define LINUX_SA_NOMASK 0x40000000
+#define LINUX_SA_ONESHOT 0x80000000
+
+/* sigprocmask actions */
+#define LINUX_SIG_BLOCK 0
+#define LINUX_SIG_UNBLOCK 1
+#define LINUX_SIG_SETMASK 2
+
+/* termio commands */
+#define LINUX_TCGETS 0x5401
+#define LINUX_TCSETS 0x5402
+#define LINUX_TCSETSW 0x5403
+#define LINUX_TCSETSF 0x5404
+#define LINUX_TCGETA 0x5405
+#define LINUX_TCSETA 0x5406
+#define LINUX_TCSETAW 0x5407
+#define LINUX_TCSETAF 0x5408
+#define LINUX_TCSBRK 0x5409
+#define LINUX_TCXONC 0x540A
+#define LINUX_TCFLSH 0x540B
+#define LINUX_TIOCEXCL 0x540C
+#define LINUX_TIOCNXCL 0x540D
+#define LINUX_TIOCSCTTY 0x540E
+#define LINUX_TIOCGPGRP 0x540F
+#define LINUX_TIOCSPGRP 0x5410
+#define LINUX_TIOCOUTQ 0x5411
+#define LINUX_TIOCSTI 0x5412
+#define LINUX_TIOCGWINSZ 0x5413
+#define LINUX_TIOCSWINSZ 0x5414
+#define LINUX_TIOCMGET 0x5415
+#define LINUX_TIOCMBIS 0x5416
+#define LINUX_TIOCMBIC 0x5417
+#define LINUX_TIOCMSET 0x5418
+#define LINUX_TIOCGSOFTCAR 0x5419
+#define LINUX_TIOCSSOFTCAR 0x541A
+#define LINUX_FIONREAD 0x541B
+#define LINUX_TIOCINQ FIONREAD
+#define LINUX_TIOCLINUX 0x541C
+#define LINUX_TIOCCONS 0x541D
+#define LINUX_TIOCGSERIAL 0x541E
+#define LINUX_TIOCSSERIAL 0x541F
+#define LINUX_TIOCPKT 0x5420
+#define LINUX_FIONBIO 0x5421
+#define LINUX_TIOCNOTTY 0x5422
+#define LINUX_TIOCSETD 0x5423
+#define LINUX_TIOCGETD 0x5424
+#define LINUX_TCSBRKP 0x5425
+#define LINUX_TIOCTTYGSTRUCT 0x5426
+#define LINUX_FIONCLEX 0x5450
+#define LINUX_FIOCLEX 0x5451
+#define LINUX_FIOASYNC 0x5452
+#define LINUX_TIOCSERCONFIG 0x5453
+#define LINUX_TIOCSERGWILD 0x5454
+#define LINUX_TIOCSERSWILD 0x5455
+#define LINUX_TIOCGLCKTRMIOS 0x5456
+#define LINUX_TIOCSLCKTRMIOS 0x5457
+
+/* line disciplines */
+#define LINUX_N_TTY 0
+#define LINUX_N_SLIP 1
+#define LINUX_N_MOUSE 2
+#define LINUX_N_PPP 3
+
+/* Linux termio c_cc values */
+#define LINUX_VINTR 0
+#define LINUX_VQUIT 1
+#define LINUX_VERASE 2
+#define LINUX_VKILL 3
+#define LINUX_VEOF 4
+#define LINUX_VTIME 5
+#define LINUX_VMIN 6
+#define LINUX_VSWTC 7
+#define LINUX_NCC 8
+
+/* Linux termios c_cc values */
+#define LINUX_VSTART 8
+#define LINUX_VSTOP 9
+#define LINUX_VSUSP 10
+#define LINUX_VEOL 11
+#define LINUX_VREPRINT 12
+#define LINUX_VDISCARD 13
+#define LINUX_VWERASE 14
+#define LINUX_VLNEXT 15
+#define LINUX_VEOL2 16
+#define LINUX_NCCS 17
+
+/* Linux c_iflag masks */
+#define LINUX_IGNBRK 0x0000001
+#define LINUX_BRKINT 0x0000002
+#define LINUX_IGNPAR 0x0000004
+#define LINUX_PARMRK 0x0000008
+#define LINUX_INPCK 0x0000010
+#define LINUX_ISTRIP 0x0000020
+#define LINUX_INLCR 0x0000040
+#define LINUX_IGNCR 0x0000080
+#define LINUX_ICRNL 0x0000100
+#define LINUX_IUCLC 0x0000200
+#define LINUX_IXON 0x0000400
+#define LINUX_IXANY 0x0000800
+#define LINUX_IXOFF 0x0001000
+#define LINUX_IMAXBEL 0x0002000
+
+/* Linux c_oflag masks */
+#define LINUX_OPOST 0x0000001
+#define LINUX_OLCUC 0x0000002
+#define LINUX_ONLCR 0x0000004
+#define LINUX_OCRNL 0x0000008
+#define LINUX_ONOCR 0x0000010
+#define LINUX_ONLRET 0x0000020
+#define LINUX_OFILL 0x0000040
+#define LINUX_OFDEL 0x0000080
+#define LINUX_NLDLY 0x0000100
+
+#define LINUX_NL0 0x0000000
+#define LINUX_NL1 0x0000100
+#define LINUX_CRDLY 0x0000600
+#define LINUX_CR0 0x0000000
+#define LINUX_CR1 0x0000200
+#define LINUX_CR2 0x0000400
+#define LINUX_CR3 0x0000600
+#define LINUX_TABDLY 0x0001800
+#define LINUX_TAB0 0x0000000
+#define LINUX_TAB1 0x0000800
+#define LINUX_TAB2 0x0001000
+#define LINUX_TAB3 0x0001800
+#define LINUX_XTABS 0x0001800
+#define LINUX_BSDLY 0x0002000
+#define LINUX_BS0 0x0000000
+#define LINUX_BS1 0x0002000
+#define LINUX_VTDLY 0x0004000
+#define LINUX_VT0 0x0000000
+#define LINUX_VT1 0x0004000
+#define LINUX_FFDLY 0x0008000
+#define LINUX_FF0 0x0000000
+#define LINUX_FF1 0x0008000
+
+#define LINUX_CBAUD 0x0000100f
+#define LINUX_B0 0x00000000
+#define LINUX_B50 0x00000001
+#define LINUX_B75 0x00000002
+#define LINUX_B110 0x00000003
+#define LINUX_B134 0x00000004
+#define LINUX_B150 0x00000005
+#define LINUX_B200 0x00000006
+#define LINUX_B300 0x00000007
+#define LINUX_B600 0x00000008
+#define LINUX_B1200 0x00000009
+#define LINUX_B1800 0x0000000a
+#define LINUX_B2400 0x0000000b
+#define LINUX_B4800 0x0000000c
+#define LINUX_B9600 0x0000000d
+#define LINUX_B19200 0x0000000e
+#define LINUX_B38400 0x0000000f
+#define LINUX_EXTA LINUX_B19200
+#define LINUX_EXTB LINUX_B38400
+#define LINUX_CBAUDEX 0x00001000
+#define LINUX_B57600 0x00001001
+#define LINUX_B115200 0x00001002
+
+#define LINUX_CSIZE 0x00000030
+#define LINUX_CS5 0x00000000
+#define LINUX_CS6 0x00000010
+#define LINUX_CS7 0x00000020
+#define LINUX_CS8 0x00000030
+#define LINUX_CSTOPB 0x00000040
+#define LINUX_CREAD 0x00000080
+#define LINUX_PARENB 0x00000100
+#define LINUX_PARODD 0x00000200
+#define LINUX_HUPCL 0x00000400
+#define LINUX_CLOCAL 0x00000800
+#define LINUX_CRTSCTS 0x80000000
+
+/* Linux c_lflag masks */
+#define LINUX_ISIG 0x00000001
+#define LINUX_ICANON 0x00000002
+#define LINUX_XCASE 0x00000004
+#define LINUX_ECHO 0x00000008
+#define LINUX_ECHOE 0x00000010
+#define LINUX_ECHOK 0x00000020
+#define LINUX_ECHONL 0x00000040
+#define LINUX_NOFLSH 0x00000080
+#define LINUX_TOSTOP 0x00000100
+#define LINUX_ECHOCTL 0x00000200
+#define LINUX_ECHOPRT 0x00000400
+#define LINUX_ECHOKE 0x00000800
+#define LINUX_FLUSHO 0x00001000
+#define LINUX_PENDIN 0x00002000
+#define LINUX_IEXTEN 0x00008000
+
+/* open/fcntl flags */
+#define LINUX_O_RDONLY 00
+#define LINUX_O_WRONLY 01
+#define LINUX_O_RDWR 02
+#define LINUX_O_CREAT 0100
+#define LINUX_O_EXCL 0200
+#define LINUX_O_NOCTTY 0400
+#define LINUX_O_TRUNC 01000
+#define LINUX_O_APPEND 02000
+#define LINUX_O_NONBLOCK 04000
+#define LINUX_O_NDELAY LINUX_O_NONBLOCK
+#define LINUX_O_SYNC 010000
+#define LINUX_FASYNC 020000
+
+/* fcntl flags */
+#define LINUX_F_DUPFD 0
+#define LINUX_F_GETFD 1
+#define LINUX_F_SETFD 2
+#define LINUX_F_GETFL 3
+#define LINUX_F_SETFL 4
+#define LINUX_F_GETLK 5
+#define LINUX_F_SETLK 6
+#define LINUX_F_SETLKW 7
+#define LINUX_F_SETOWN 8
+#define LINUX_F_GETOWN 9
+
+#define LINUX_F_RDLCK 0
+#define LINUX_F_WRLCK 1
+#define LINUX_F_UNLCK 2
+
+/* mmap options */
+#define LINUX_MAP_SHARED 0x0001
+#define LINUX_MAP_PRIVATE 0x0002
+#define LINUX_MAP_FIXED 0x0010
+#define LINUX_MAP_ANON 0x0020
+
+/* SystemV ipc defines */
+#define LINUX_SEMOP 1
+#define LINUX_SEMGET 2
+#define LINUX_SEMCTL 3
+#define LINUX_MSGSND 11
+#define LINUX_MSGRCV 12
+#define LINUX_MSGGET 13
+#define LINUX_MSGCTL 14
+#define LINUX_SHMAT 21
+#define LINUX_SHMDT 22
+#define LINUX_SHMGET 23
+#define LINUX_SHMCTL 24
+
+#define LINUX_IPC_RMID 0
+#define LINUX_IPC_SET 1
+#define LINUX_IPC_STAT 2
+#define LINUX_IPC_INFO 3
+
+#define LINUX_SHM_LOCK 11
+#define LINUX_SHM_UNLOCK 12
+#define LINUX_SHM_STAT 13
+#define LINUX_SHM_INFO 14
+
+#define LINUX_SHM_RDONLY 0x1000
+#define LINUX_SHM_RND 0x2000
+#define LINUX_SHM_REMAP 0x4000
+
+/* Socket defines */
+#define LINUX_SOCKET 1
+#define LINUX_BIND 2
+#define LINUX_CONNECT 3
+#define LINUX_LISTEN 4
+#define LINUX_ACCEPT 5
+#define LINUX_GETSOCKNAME 6
+#define LINUX_GETPEERNAME 7
+#define LINUX_SOCKETPAIR 8
+#define LINUX_SEND 9
+#define LINUX_RECV 10
+#define LINUX_SENDTO 11
+#define LINUX_RECVFROM 12
+#define LINUX_SHUTDOWN 13
+#define LINUX_SETSOCKOPT 14
+#define LINUX_GETSOCKOPT 15
+
+#define LINUX_AF_UNSPEC 0
+#define LINUX_AF_UNIX 1
+#define LINUX_AF_INET 2
+#define LINUX_AF_AX25 3
+#define LINUX_AF_IPX 4
+#define LINUX_AF_APPLETALK 5
+
+#define LINUX_SOL_SOCKET 1
+#define LINUX_SOL_IP 0
+#define LINUX_SOL_IPX 256
+#define LINUX_SOL_AX25 257
+#define LINUX_SOL_TCP 6
+#define LINUX_SOL_UDP 17
+
+#define LINUX_SO_DEBUG 1
+#define LINUX_SO_REUSEADDR 2
+#define LINUX_SO_TYPE 3
+#define LINUX_SO_ERROR 4
+#define LINUX_SO_DONTROUTE 5
+#define LINUX_SO_BROADCAST 6
+#define LINUX_SO_SNDBUF 7
+#define LINUX_SO_RCVBUF 8
+#define LINUX_SO_KEEPALIVE 9
+#define LINUX_SO_OOBINLINE 10
+#define LINUX_SO_NO_CHECK 11
+#define LINUX_SO_PRIORITY 12
+#define LINUX_SO_LINGER 13
+
+#define LINUX_IP_TOS 1
+#define LINUX_IP_TTL 2
+
+#endif /* LINUX_H */
diff --git a/sys/i386/linux/linux_dummy.c b/sys/i386/linux/linux_dummy.c
new file mode 100644
index 0000000000000..13288acf297c6
--- /dev/null
+++ b/sys/i386/linux/linux_dummy.c
@@ -0,0 +1,316 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_dummy.c,v 1.3 1995/06/08 13:50:52 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/errno.h>
+#include <vm/vm.h>
+
+int
+linux_setup(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): setup() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_break(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): break() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_stat(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): stat() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_fstat(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): fstat() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_mount(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): mount() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_umount(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): umount() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_stime(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): stime() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ptrace(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ptrace() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_pause(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): pause() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_stty(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): stty() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_gtty(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): gtty() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_nice(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): nice() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ftime(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ftime() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_prof(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): prof() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_signal(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): signal() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_phys(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): phys() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_lock(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): lock() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_mpx(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): mpx() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ulimit(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ulimit() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_olduname(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): olduname() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ustat(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ustat() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ioperm(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ioperm() not supported\n", p->p_pid);
+ return 0; /* EINVAL SOS XXX */
+}
+
+int
+linux_syslog(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): syslog() not supported (BSD sigreturn)\n",p->p_pid);
+ return sigreturn(p, args, retval);
+}
+
+int
+linux_iopl(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): iopl() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_vhangup(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): vhangup() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_idle(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): idle() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_vm86(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): vm86() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_swapoff(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): swapoff() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_sysinfo(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): sysinfo() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_sigreturn(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): sigreturn() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_clone(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): clone() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_uname(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): uname() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_modify_ldt(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): modify_ldt() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_adjtimex(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): adjtimex() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_create_module(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): create_module() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_init_module(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): init_module() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_delete_module(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): delete_module() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_get_kernel_syms(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): get_kernel_syms() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_quotactl(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): quotactl() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_bdflush(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): bdflush() not supported\n", p->p_pid);
+ return ENOSYS;
+}
diff --git a/sys/i386/linux/linux_file.c b/sys/i386/linux/linux_file.c
new file mode 100644
index 0000000000000..b846068ccd9ab
--- /dev/null
+++ b/sys/i386/linux/linux_file.c
@@ -0,0 +1,436 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_file.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vnode.h>
+#include <sys/malloc.h>
+#include <sys/exec.h>
+#include <sys/dirent.h>
+#include <vm/vm.h>
+#include <ufs/ufs/dir.h>
+
+
+struct linux_creat_args {
+ char *path;
+ int mode;
+};
+
+int
+linux_creat(struct proc *p, struct linux_creat_args *args, int *retval)
+{
+ struct {
+ char *path;
+ int flags;
+ int mode;
+ } bsd_open_args;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): creat(%s, %d)\n",
+ p->p_pid, args->path, args->mode);
+#endif
+ bsd_open_args.path = args->path;
+ bsd_open_args.mode = args->mode;
+ bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC;
+ return open(p, &bsd_open_args, retval);
+}
+
+struct linux_open_args {
+ char *path;
+ int flags;
+ int mode;
+};
+
+int
+linux_open(struct proc *p, struct linux_open_args *args, int *retval)
+{
+ struct {
+ char *path;
+ int flags;
+ int mode;
+ } bsd_open_args;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n",
+ p->p_pid, args->path, args->flags, args->mode);
+#endif
+ bsd_open_args.flags = 0;
+ if (args->flags & LINUX_O_RDONLY)
+ bsd_open_args.flags |= O_RDONLY;
+ if (args->flags & LINUX_O_WRONLY)
+ bsd_open_args.flags |= O_WRONLY;
+ if (args->flags & LINUX_O_RDWR)
+ bsd_open_args.flags |= O_RDWR;
+ if (args->flags & LINUX_O_NDELAY)
+ bsd_open_args.flags |= O_NONBLOCK;
+ if (args->flags & LINUX_O_APPEND)
+ bsd_open_args.flags |= O_APPEND;
+ if (args->flags & LINUX_O_SYNC)
+ bsd_open_args.flags |= O_FSYNC;
+ if (args->flags & LINUX_O_NONBLOCK)
+ bsd_open_args.flags |= O_NONBLOCK;
+ if (args->flags & LINUX_FASYNC)
+ bsd_open_args.flags |= O_ASYNC;
+ if (args->flags & LINUX_O_CREAT)
+ bsd_open_args.flags |= O_CREAT;
+ if (args->flags & LINUX_O_TRUNC)
+ bsd_open_args.flags |= O_TRUNC;
+ if (args->flags & LINUX_O_EXCL)
+ bsd_open_args.flags |= O_EXCL;
+ if (args->flags & LINUX_O_NOCTTY)
+ bsd_open_args.flags |= O_NOCTTY;
+ bsd_open_args.path = args->path;
+ bsd_open_args.mode = args->mode;
+
+ error = open(p, &bsd_open_args, retval);
+ if (!error && !(bsd_open_args.flags & O_NOCTTY) &&
+ SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp = fdp->fd_ofiles[*retval];
+
+ if (fp->f_type == DTYPE_VNODE)
+ (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p);
+ }
+ return error;
+}
+
+struct linux_flock {
+ short l_type;
+ short l_whence;
+ linux_off_t l_start;
+ linux_off_t l_len;
+ linux_pid_t l_pid;
+};
+
+static void
+linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock)
+{
+ switch (linux_flock->l_type) {
+ case LINUX_F_RDLCK:
+ bsd_flock->l_type = F_RDLCK;
+ break;
+ case LINUX_F_WRLCK:
+ bsd_flock->l_type = F_WRLCK;
+ break;
+ case LINUX_F_UNLCK:
+ bsd_flock->l_type = F_UNLCK;
+ break;
+ }
+ bsd_flock->l_whence = linux_flock->l_whence;
+ bsd_flock->l_start = (off_t)linux_flock->l_start;
+ bsd_flock->l_len = (off_t)linux_flock->l_len;
+ bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
+}
+
+static void
+bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock)
+{
+ switch (bsd_flock->l_type) {
+ case F_RDLCK:
+ linux_flock->l_type = LINUX_F_RDLCK;
+ break;
+ case F_WRLCK:
+ linux_flock->l_type = LINUX_F_WRLCK;
+ break;
+ case F_UNLCK:
+ linux_flock->l_type = LINUX_F_UNLCK;
+ break;
+ }
+ linux_flock->l_whence = bsd_flock->l_whence;
+ linux_flock->l_start = (linux_off_t)bsd_flock->l_start;
+ linux_flock->l_len = (linux_off_t)bsd_flock->l_len;
+ linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid;
+}
+
+struct linux_fcntl_args {
+ int fd;
+ int cmd;
+ int arg;
+};
+
+int
+linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval)
+{
+ int error, result;
+ struct fcntl_args {
+ int fd;
+ int cmd;
+ int arg;
+ } fcntl_args;
+ struct linux_flock linux_flock;
+ struct flock *bsd_flock =
+ (struct flock *)ua_alloc_init(sizeof(struct flock));
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): fcntl(%d, %08x, *)\n",
+ p->p_pid, args->fd, args->cmd);
+#endif
+ fcntl_args.fd = args->fd;
+ fcntl_args.arg = 0;
+
+ switch (args->cmd) {
+ case LINUX_F_DUPFD:
+ fcntl_args.cmd = F_DUPFD;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETFD:
+ fcntl_args.cmd = F_GETFD;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_SETFD:
+ fcntl_args.cmd = F_SETFD;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETFL:
+ fcntl_args.cmd = F_GETFL;
+ error = fcntl(p, &fcntl_args, &result);
+ *retval = 0;
+ if (result & O_RDONLY) *retval |= LINUX_O_RDONLY;
+ if (result & O_WRONLY) *retval |= LINUX_O_WRONLY;
+ if (result & O_RDWR) *retval |= LINUX_O_RDWR;
+ if (result & O_NDELAY) *retval |= LINUX_O_NONBLOCK;
+ if (result & O_APPEND) *retval |= LINUX_O_APPEND;
+ if (result & O_FSYNC) *retval |= LINUX_O_SYNC;
+ return error;
+
+ case LINUX_F_SETFL:
+ if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK;
+ if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND;
+ if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC;
+ fcntl_args.cmd = F_SETFL;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETLK:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_GETLK;
+ fcntl_args.arg = (int)bsd_flock;
+ if (error = fcntl(p, &fcntl_args, retval))
+ return error;
+ bsd_to_linux_flock(bsd_flock, &linux_flock);
+ return copyout((caddr_t)&linux_flock, (caddr_t)args->arg,
+ sizeof(struct linux_flock));
+
+ case LINUX_F_SETLK:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_SETLK;
+ fcntl_args.arg = (int)bsd_flock;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_SETLKW:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_SETLKW;
+ fcntl_args.arg = (int)bsd_flock;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_SETOWN:
+ fcntl_args.cmd = F_SETOWN;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETOWN:
+ fcntl_args.cmd = F_GETOWN;
+ return fcntl(p, &fcntl_args, retval);
+ }
+ return EINVAL;
+}
+
+struct linux_lseek_args {
+ int fdes;
+ unsigned long off;
+ int whence;
+};
+
+int
+linux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval)
+{
+
+ struct lseek_args {
+ int fdes;
+ int pad;
+ off_t off;
+ int whence;
+ } tmp_args;
+ off_t tmp_retval;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): lseek(%d, %d, %d)\n",
+ p->p_pid, args->fdes, args->off, args->whence);
+#endif
+ tmp_args.fdes = args->fdes;
+ tmp_args.off = (off_t)args->off;
+ tmp_args.whence = args->whence;
+ error = lseek(p, &tmp_args, &tmp_retval);
+ *retval = (int)tmp_retval;
+ return error;
+}
+
+struct linux_dirent {
+ long dino;
+ linux_off_t doff;
+ unsigned short dreclen;
+ char dname[LINUX_NAME_MAX + 1];
+};
+
+#define LINUX_RECLEN(de,namlen) \
+ ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1))
+
+struct linux_readdir_args {
+ int fd;
+ struct linux_dirent *dent;
+ unsigned int count;
+};
+
+int
+linux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval)
+{
+ register struct dirent *bdp;
+ struct vnode *vp;
+ caddr_t inp, buf; /* BSD-format */
+ int len, reclen; /* BSD-format */
+ caddr_t outp; /* Linux-format */
+ int resid, linuxreclen=0; /* Linux-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ struct vattr va;
+ off_t off;
+ struct linux_dirent linux_dirent;
+ int buflen, error, eofflag, nbytes, justone;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): readdir(%d, *, %d)\n",
+ p->p_pid, args->fd, args->count);
+#endif
+ if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0)
+ return (error);
+
+ if ((fp->f_flag & FREAD) == 0)
+ return (EBADF);
+
+ vp = (struct vnode *) fp->f_data;
+
+ if (vp->v_type != VDIR)
+ return (EINVAL);
+
+ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
+ return error;
+
+ nbytes = args->count;
+ if (nbytes == 1) {
+ nbytes = sizeof (struct linux_dirent);
+ justone = 1;
+ }
+ else
+ justone = 0;
+
+ buflen = max(va.va_blocksize, nbytes);
+ buf = malloc(buflen, M_TEMP, M_WAITOK);
+ VOP_LOCK(vp);
+ off = fp->f_offset;
+again:
+ aiov.iov_base = buf;
+ aiov.iov_len = buflen;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_procp = p;
+ auio.uio_resid = buflen;
+ auio.uio_offset = off;
+
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *) 0, 0);
+ if (error)
+ goto out;
+
+ inp = buf;
+ outp = (caddr_t) args->dent;
+ resid = nbytes;
+ if ((len = buflen - auio.uio_resid) == 0)
+ goto eof;
+
+ while (len > 0) {
+ reclen = ((struct dirent *) inp)->d_reclen;
+ if (reclen & 3)
+ panic("linux_readdir");
+ off += reclen;
+ bdp = (struct dirent *) inp;
+ if (bdp->d_fileno == 0) {
+ inp += reclen;
+ continue;
+ }
+ linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
+ if (reclen > len || resid < linuxreclen) {
+ outp++;
+ break;
+ }
+ linux_dirent.dino = (long) bdp->d_fileno;
+ linux_dirent.doff = (linux_off_t) linuxreclen;
+ linux_dirent.dreclen = (u_short) bdp->d_namlen;
+ strcpy(linux_dirent.dname, bdp->d_name);
+ if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen)))
+ goto out;
+ inp += reclen;
+ outp += linuxreclen;
+ resid -= linuxreclen;
+ len -= reclen;
+ if (justone)
+ break;
+ }
+
+ if (outp == (caddr_t) args->dent)
+ goto again;
+ fp->f_offset = off;
+
+ if (justone)
+ nbytes = resid + linuxreclen;
+eof:
+ *retval = nbytes - resid;
+out:
+ VOP_UNLOCK(vp);
+ free(buf, M_TEMP);
+ return error;
+}
diff --git a/sys/i386/linux/linux_generic.c b/sys/i386/linux/linux_generic.c
new file mode 100644
index 0000000000000..48df332aeb98e
--- /dev/null
+++ b/sys/i386/linux/linux_generic.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_generic.c,v 1.3 1995/06/25 17:30:46 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+
+
+static caddr_t ua_ptr = NULL;
+
+caddr_t ua_alloc_init(int len)
+{
+ caddr_t ptr;
+
+ ptr = (caddr_t)ALIGN((PS_STRINGS));
+ ptr += sizeof(struct ps_strings);
+ ua_ptr = (caddr_t)(ptr + ALIGN(len));
+ return ptr;
+}
+
+caddr_t ua_alloc(int len)
+{
+ caddr_t ptr;
+
+ ptr = ua_ptr;
+ ua_ptr += ALIGN(len);
+ return ptr;
+}
diff --git a/sys/i386/linux/linux_ioctl.c b/sys/i386/linux/linux_ioctl.c
new file mode 100644
index 0000000000000..12adff4a18a85
--- /dev/null
+++ b/sys/i386/linux/linux_ioctl.c
@@ -0,0 +1,495 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_ioctl.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/ioctl_compat.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/tty.h>
+#include <sys/termios.h>
+#include <machine/console.h>
+
+
+struct linux_termios {
+ unsigned long c_iflag;
+ unsigned long c_oflag;
+ unsigned long c_cflag;
+ unsigned long c_lflag;
+ unsigned char c_line;
+ unsigned char c_cc[LINUX_NCCS];
+};
+
+struct linux_winsize {
+ unsigned short ws_row, ws_col;
+ unsigned short ws_xpixel, ws_ypixel;
+};
+
+static struct speedtab sptab[] = {
+ { 0, 0 }, { 50, 1 }, { 75, 2 }, { 110, 3 },
+ { 134, 4 }, { 135, 4 }, { 150, 5 }, { 200, 6 },
+ { 300, 7 }, { 600, 8 }, { 1200, 9 }, { 1800, 10 },
+ { 2400, 11 }, { 4800, 12 }, { 9600, 13 },
+ { 19200, 14 }, { 38400, 15 },
+ { 57600, 4097 }, { 115200, 4098 }, {-1, -1 }
+};
+
+static int
+linux_to_bsd_speed(int code, struct speedtab *table)
+{
+ for ( ; table->sp_code != -1; table++)
+ if (table->sp_code == code)
+ return (table->sp_speed);
+ return -1;
+}
+
+static int
+bsd_to_linux_speed(int speed, struct speedtab *table)
+{
+ for ( ; table->sp_speed != -1; table++)
+ if (table->sp_speed == speed)
+ return (table->sp_code);
+ return -1;
+}
+
+static void
+bsd_to_linux_termios(struct termios *bsd_termios,
+ struct linux_termios *linux_termios)
+{
+ int i, speed;
+
+#ifdef DEBUG
+ printf("LINUX: BSD termios structure (input):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
+ bsd_termios->c_iflag, bsd_termios->c_oflag,
+ bsd_termios->c_cflag, bsd_termios->c_lflag,
+ bsd_termios->c_ispeed, bsd_termios->c_ospeed);
+ printf("c_cc ");
+ for (i=0; i<NCCS; i++)
+ printf("%02x ", bsd_termios->c_cc[i]);
+ printf("\n");
+#endif
+ linux_termios->c_iflag = 0;
+ if (bsd_termios->c_iflag & IGNBRK)
+ linux_termios->c_iflag |= LINUX_IGNBRK;
+ if (bsd_termios->c_iflag & BRKINT)
+ linux_termios->c_iflag |= LINUX_BRKINT;
+ if (bsd_termios->c_iflag & IGNPAR)
+ linux_termios->c_iflag |= LINUX_IGNPAR;
+ if (bsd_termios->c_iflag & PARMRK)
+ linux_termios->c_iflag |= LINUX_PARMRK;
+ if (bsd_termios->c_iflag & INPCK)
+ linux_termios->c_iflag |= LINUX_INPCK;
+ if (bsd_termios->c_iflag & ISTRIP)
+ linux_termios->c_iflag |= LINUX_ISTRIP;
+ if (bsd_termios->c_iflag & INLCR)
+ linux_termios->c_iflag |= LINUX_INLCR;
+ if (bsd_termios->c_iflag & IGNCR)
+ linux_termios->c_iflag |= LINUX_IGNCR;
+ if (bsd_termios->c_iflag & ICRNL)
+ linux_termios->c_iflag |= LINUX_ICRNL;
+ if (bsd_termios->c_iflag & IXON)
+ linux_termios->c_iflag |= LINUX_IXANY;
+ if (bsd_termios->c_iflag & IXON)
+ linux_termios->c_iflag |= LINUX_IXON;
+ if (bsd_termios->c_iflag & IXOFF)
+ linux_termios->c_iflag |= LINUX_IXOFF;
+ if (bsd_termios->c_iflag & IMAXBEL)
+ linux_termios->c_iflag |= LINUX_IMAXBEL;
+
+ linux_termios->c_oflag = 0;
+ if (bsd_termios->c_oflag & OPOST)
+ linux_termios->c_oflag |= LINUX_OPOST;
+ if (bsd_termios->c_oflag & ONLCR)
+ linux_termios->c_oflag |= LINUX_ONLCR;
+ if (bsd_termios->c_oflag & OXTABS)
+ linux_termios->c_oflag |= LINUX_XTABS;
+
+ linux_termios->c_cflag =
+ bsd_to_linux_speed(bsd_termios->c_ispeed, sptab);
+ linux_termios->c_cflag |= (bsd_termios->c_cflag & CSIZE) >> 4;
+ if (bsd_termios->c_cflag & CSTOPB)
+ linux_termios->c_cflag |= LINUX_CSTOPB;
+ if (bsd_termios->c_cflag & CREAD)
+ linux_termios->c_cflag |= LINUX_CREAD;
+ if (bsd_termios->c_cflag & PARENB)
+ linux_termios->c_cflag |= LINUX_PARENB;
+ if (bsd_termios->c_cflag & PARODD)
+ linux_termios->c_cflag |= LINUX_PARODD;
+ if (bsd_termios->c_cflag & HUPCL)
+ linux_termios->c_cflag |= LINUX_HUPCL;
+ if (bsd_termios->c_cflag & CLOCAL)
+ linux_termios->c_cflag |= LINUX_CLOCAL;
+ if (bsd_termios->c_cflag & CRTSCTS)
+ linux_termios->c_cflag |= LINUX_CRTSCTS;
+
+ linux_termios->c_lflag = 0;
+ if (bsd_termios->c_lflag & ISIG)
+ linux_termios->c_lflag |= LINUX_ISIG;
+ if (bsd_termios->c_lflag & ICANON)
+ linux_termios->c_lflag |= LINUX_ICANON;
+ if (bsd_termios->c_lflag & ECHO)
+ linux_termios->c_lflag |= LINUX_ECHO;
+ if (bsd_termios->c_lflag & ECHOE)
+ linux_termios->c_lflag |= LINUX_ECHOE;
+ if (bsd_termios->c_lflag & ECHOK)
+ linux_termios->c_lflag |= LINUX_ECHOK;
+ if (bsd_termios->c_lflag & ECHONL)
+ linux_termios->c_lflag |= LINUX_ECHONL;
+ if (bsd_termios->c_lflag & NOFLSH)
+ linux_termios->c_lflag |= LINUX_NOFLSH;
+ if (bsd_termios->c_lflag & TOSTOP)
+ linux_termios->c_lflag |= LINUX_TOSTOP;
+ if (bsd_termios->c_lflag & ECHOCTL)
+ linux_termios->c_lflag |= LINUX_ECHOCTL;
+ if (bsd_termios->c_lflag & ECHOPRT)
+ linux_termios->c_lflag |= LINUX_ECHOPRT;
+ if (bsd_termios->c_lflag & ECHOKE)
+ linux_termios->c_lflag |= LINUX_ECHOKE;
+ if (bsd_termios->c_lflag & FLUSHO)
+ linux_termios->c_lflag |= LINUX_FLUSHO;
+ if (bsd_termios->c_lflag & PENDIN)
+ linux_termios->c_lflag |= LINUX_PENDIN;
+ if (bsd_termios->c_lflag & IEXTEN)
+ linux_termios->c_lflag |= LINUX_IEXTEN;
+
+ for (i=0; i<LINUX_NCCS; i++)
+ linux_termios->c_cc[i] = _POSIX_VDISABLE;
+ linux_termios->c_cc[LINUX_VINTR] = bsd_termios->c_cc[VINTR];
+ linux_termios->c_cc[LINUX_VQUIT] = bsd_termios->c_cc[VQUIT];
+ linux_termios->c_cc[LINUX_VERASE] = bsd_termios->c_cc[VERASE];
+ linux_termios->c_cc[LINUX_VKILL] = bsd_termios->c_cc[VKILL];
+ linux_termios->c_cc[LINUX_VEOF] = bsd_termios->c_cc[VEOF];
+ linux_termios->c_cc[LINUX_VEOL] = bsd_termios->c_cc[VEOL];
+ linux_termios->c_cc[LINUX_VMIN] = bsd_termios->c_cc[VMIN];
+ linux_termios->c_cc[LINUX_VTIME] = bsd_termios->c_cc[VTIME];
+ linux_termios->c_cc[LINUX_VEOL2] = bsd_termios->c_cc[VEOL2];
+ linux_termios->c_cc[LINUX_VSWTC] = _POSIX_VDISABLE;
+ linux_termios->c_cc[LINUX_VSUSP] = bsd_termios->c_cc[VSUSP];
+ linux_termios->c_cc[LINUX_VSTART] = bsd_termios->c_cc[VSTART];
+ linux_termios->c_cc[LINUX_VSTOP] = bsd_termios->c_cc[VSTOP];
+ linux_termios->c_cc[LINUX_VREPRINT] = bsd_termios->c_cc[VREPRINT];
+ linux_termios->c_cc[LINUX_VDISCARD] = bsd_termios->c_cc[VDISCARD];
+ linux_termios->c_cc[LINUX_VWERASE] = bsd_termios->c_cc[VWERASE];
+ linux_termios->c_cc[LINUX_VLNEXT] = bsd_termios->c_cc[VLNEXT];
+
+ linux_termios->c_line = 0;
+#ifdef DEBUG
+ printf("LINUX: LINUX termios structure (output):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
+ linux_termios->c_iflag, linux_termios->c_oflag,
+ linux_termios->c_cflag, linux_termios->c_lflag,
+ linux_termios->c_line);
+ printf("c_cc ");
+ for (i=0; i<LINUX_NCCS; i++)
+ printf("%02x ", linux_termios->c_cc[i]);
+ printf("\n");
+#endif
+}
+
+static void
+linux_to_bsd_termios(struct linux_termios *linux_termios,
+ struct termios *bsd_termios)
+{
+ int i, speed;
+#ifdef DEBUG
+ printf("LINUX: LINUX termios structure (input):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
+ linux_termios->c_iflag, linux_termios->c_oflag,
+ linux_termios->c_cflag, linux_termios->c_lflag,
+ linux_termios->c_line);
+ printf("c_cc ");
+ for (i=0; i<LINUX_NCCS; i++)
+ printf("%02x ", linux_termios->c_cc[i]);
+ printf("\n");
+#endif
+ bsd_termios->c_iflag = 0;
+ if (linux_termios->c_iflag & LINUX_IGNBRK)
+ bsd_termios->c_iflag |= IGNBRK;
+ if (linux_termios->c_iflag & LINUX_BRKINT)
+ bsd_termios->c_iflag |= BRKINT;
+ if (linux_termios->c_iflag & LINUX_IGNPAR)
+ bsd_termios->c_iflag |= IGNPAR;
+ if (linux_termios->c_iflag & LINUX_PARMRK)
+ bsd_termios->c_iflag |= PARMRK;
+ if (linux_termios->c_iflag & LINUX_INPCK)
+ bsd_termios->c_iflag |= INPCK;
+ if (linux_termios->c_iflag & LINUX_ISTRIP)
+ bsd_termios->c_iflag |= ISTRIP;
+ if (linux_termios->c_iflag & LINUX_INLCR)
+ bsd_termios->c_iflag |= INLCR;
+ if (linux_termios->c_iflag & LINUX_IGNCR)
+ bsd_termios->c_iflag |= IGNCR;
+ if (linux_termios->c_iflag & LINUX_ICRNL)
+ bsd_termios->c_iflag |= ICRNL;
+ if (linux_termios->c_iflag & LINUX_IXON)
+ bsd_termios->c_iflag |= IXANY;
+ if (linux_termios->c_iflag & LINUX_IXON)
+ bsd_termios->c_iflag |= IXON;
+ if (linux_termios->c_iflag & LINUX_IXOFF)
+ bsd_termios->c_iflag |= IXOFF;
+ if (linux_termios->c_iflag & LINUX_IMAXBEL)
+ bsd_termios->c_iflag |= IMAXBEL;
+
+ bsd_termios->c_oflag = 0;
+ if (linux_termios->c_oflag & LINUX_OPOST)
+ bsd_termios->c_oflag |= OPOST;
+ if (linux_termios->c_oflag & LINUX_ONLCR)
+ bsd_termios->c_oflag |= ONLCR;
+ if (linux_termios->c_oflag & LINUX_XTABS)
+ bsd_termios->c_oflag |= OXTABS;
+
+ bsd_termios->c_cflag = (linux_termios->c_cflag & LINUX_CSIZE) << 4;
+ if (linux_termios->c_cflag & LINUX_CSTOPB)
+ bsd_termios->c_cflag |= CSTOPB;
+ if (linux_termios->c_cflag & LINUX_PARENB)
+ bsd_termios->c_cflag |= PARENB;
+ if (linux_termios->c_cflag & LINUX_PARODD)
+ bsd_termios->c_cflag |= PARODD;
+ if (linux_termios->c_cflag & LINUX_HUPCL)
+ bsd_termios->c_cflag |= HUPCL;
+ if (linux_termios->c_cflag & LINUX_CLOCAL)
+ bsd_termios->c_cflag |= CLOCAL;
+ if (linux_termios->c_cflag & LINUX_CRTSCTS)
+ bsd_termios->c_cflag |= CRTSCTS;
+
+ bsd_termios->c_lflag = 0;
+ if (linux_termios->c_lflag & LINUX_ISIG)
+ bsd_termios->c_lflag |= ISIG;
+ if (linux_termios->c_lflag & LINUX_ICANON)
+ bsd_termios->c_lflag |= ICANON;
+ if (linux_termios->c_lflag & LINUX_ECHO)
+ bsd_termios->c_lflag |= ECHO;
+ if (linux_termios->c_lflag & LINUX_ECHOE)
+ bsd_termios->c_lflag |= ECHOE;
+ if (linux_termios->c_lflag & LINUX_ECHOK)
+ bsd_termios->c_lflag |= ECHOK;
+ if (linux_termios->c_lflag & LINUX_ECHONL)
+ bsd_termios->c_lflag |= ECHONL;
+ if (linux_termios->c_lflag & LINUX_NOFLSH)
+ bsd_termios->c_lflag |= NOFLSH;
+ if (linux_termios->c_lflag & LINUX_TOSTOP)
+ bsd_termios->c_lflag |= TOSTOP;
+ if (linux_termios->c_lflag & LINUX_ECHOCTL)
+ bsd_termios->c_lflag |= ECHOCTL;
+ if (linux_termios->c_lflag & LINUX_ECHOPRT)
+ bsd_termios->c_lflag |= ECHOPRT;
+ if (linux_termios->c_lflag & LINUX_ECHOKE)
+ bsd_termios->c_lflag |= ECHOKE;
+ if (linux_termios->c_lflag & LINUX_FLUSHO)
+ bsd_termios->c_lflag |= FLUSHO;
+ if (linux_termios->c_lflag & LINUX_PENDIN)
+ bsd_termios->c_lflag |= PENDIN;
+ if (linux_termios->c_lflag & IEXTEN)
+ bsd_termios->c_lflag |= IEXTEN;
+
+ for (i=0; i<NCCS; i++)
+ bsd_termios->c_cc[i] = _POSIX_VDISABLE;
+ bsd_termios->c_cc[VINTR] = linux_termios->c_cc[LINUX_VINTR];
+ bsd_termios->c_cc[VQUIT] = linux_termios->c_cc[LINUX_VQUIT];
+ bsd_termios->c_cc[VERASE] = linux_termios->c_cc[LINUX_VERASE];
+ bsd_termios->c_cc[VKILL] = linux_termios->c_cc[LINUX_VKILL];
+ bsd_termios->c_cc[VEOF] = linux_termios->c_cc[LINUX_VEOF];
+ bsd_termios->c_cc[VEOL] = linux_termios->c_cc[LINUX_VEOL];
+ bsd_termios->c_cc[VMIN] = linux_termios->c_cc[LINUX_VMIN];
+ bsd_termios->c_cc[VTIME] = linux_termios->c_cc[LINUX_VTIME];
+ bsd_termios->c_cc[VEOL2] = linux_termios->c_cc[LINUX_VEOL2];
+ bsd_termios->c_cc[VSUSP] = linux_termios->c_cc[LINUX_VSUSP];
+ bsd_termios->c_cc[VSTART] = linux_termios->c_cc[LINUX_VSTART];
+ bsd_termios->c_cc[VSTOP] = linux_termios->c_cc[LINUX_VSTOP];
+ bsd_termios->c_cc[VREPRINT] = linux_termios->c_cc[LINUX_VREPRINT];
+ bsd_termios->c_cc[VDISCARD] = linux_termios->c_cc[LINUX_VDISCARD];
+ bsd_termios->c_cc[VWERASE] = linux_termios->c_cc[LINUX_VWERASE];
+ bsd_termios->c_cc[VLNEXT] = linux_termios->c_cc[LINUX_VLNEXT];
+
+ bsd_termios->c_ispeed = bsd_termios->c_ospeed =
+ linux_to_bsd_speed(linux_termios->c_cflag & LINUX_CBAUD, sptab);
+#ifdef DEBUG
+ printf("LINUX: BSD termios structure (output):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
+ bsd_termios->c_iflag, bsd_termios->c_oflag,
+ bsd_termios->c_cflag, bsd_termios->c_lflag,
+ bsd_termios->c_ispeed, bsd_termios->c_ospeed);
+ printf("c_cc ");
+ for (i=0; i<NCCS; i++)
+ printf("%02x ", bsd_termios->c_cc[i]);
+ printf("\n");
+#endif
+}
+
+
+struct linux_ioctl_args {
+ int fd;
+ int cmd;
+ int arg;
+};
+
+int
+linux_ioctl(struct proc *p, struct linux_ioctl_args *args, int *retval)
+{
+ struct termios bsd_termios;
+ struct winsize bsd_winsize;
+ struct linux_termios linux_termios;
+ struct linux_winsize linux_winsize;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ int (*func)();
+ int bsd_line, linux_line;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): ioctl(%d, %04x, *)\n",
+ p->p_pid, args->fd, args->cmd);
+#endif
+ if ((unsigned)args->fd >= fdp->fd_nfiles
+ || (fp = fdp->fd_ofiles[args->fd]) == 0)
+ return EBADF;
+
+ if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) {
+ return EBADF;
+ }
+
+ func = fp->f_ops->fo_ioctl;
+ switch (args->cmd) {
+ case LINUX_TCGETS:
+ if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0)
+ return error;
+ bsd_to_linux_termios(&bsd_termios, &linux_termios);
+ return copyout((caddr_t)&linux_termios, (caddr_t)args->arg,
+ sizeof(linux_termios));
+
+ case LINUX_TCSETS:
+ linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
+ return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p);
+
+ case LINUX_TCSETSW:
+ linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
+ return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p);
+
+ case LINUX_TCSETSF:
+ linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
+ return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p);
+
+ case LINUX_TIOCGPGRP:
+ args->cmd = TIOCGPGRP;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCSPGRP:
+ args->cmd = TIOCSPGRP;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCGWINSZ:
+ args->cmd = TIOCGWINSZ;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCSWINSZ:
+ args->cmd = TIOCSWINSZ;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIONREAD:
+ args->cmd = FIONREAD;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIONBIO:
+ args->cmd = FIONBIO;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIOASYNC:
+ args->cmd = FIOASYNC;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIONCLEX:
+ args->cmd = FIONCLEX;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIOCLEX:
+ args->cmd = FIOCLEX;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCEXCL:
+ args->cmd = TIOCEXCL;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCNXCL:
+ args->cmd = TIOCNXCL;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCCONS:
+ args->cmd = TIOCCONS;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCNOTTY:
+ args->cmd = TIOCNOTTY;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCSETD:
+ switch (args->arg) {
+ case LINUX_N_TTY:
+ bsd_line = TTYDISC;
+ return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
+ case LINUX_N_SLIP:
+ bsd_line = SLIPDISC;
+ return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
+ case LINUX_N_PPP:
+ bsd_line = PPPDISC;
+ return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
+ default:
+ return EINVAL;
+ }
+ break;
+
+ case LINUX_TIOCGETD:
+ bsd_line = TTYDISC;
+ if (error =(*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p))
+ return error;
+ switch (bsd_line) {
+ case TTYDISC:
+ linux_line = LINUX_N_TTY;
+ break;
+ case SLIPDISC:
+ linux_line = LINUX_N_SLIP;
+ break;
+ case PPPDISC:
+ linux_line = LINUX_N_PPP;
+ break;
+ default:
+ return EINVAL;
+ }
+ return copyout(&linux_line, (caddr_t)args->arg,
+ sizeof(int));
+ }
+ uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n",
+ args->fd, (args->cmd&0xffff00)>>8,
+ (args->cmd&0xffff00)>>8, args->cmd&0xff);
+ return EINVAL;
+}
diff --git a/sys/i386/linux/linux_ipc.c b/sys/i386/linux/linux_ipc.c
new file mode 100644
index 0000000000000..b38b229c691f5
--- /dev/null
+++ b/sys/i386/linux/linux_ipc.c
@@ -0,0 +1,308 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_ipc.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/proc.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/msg.h>
+
+#include <vm/vm.h>
+
+struct linux_ipc_perm {
+ linux_key_t key;
+ unsigned short uid;
+ unsigned short gid;
+ unsigned short cuid;
+ unsigned short cgid;
+ unsigned short mode;
+ unsigned short seq;
+};
+
+static void
+linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
+{
+ bpp->key = lpp->key;
+ bpp->uid = lpp->uid;
+ bpp->gid = lpp->gid;
+ bpp->cuid = lpp->cuid;
+ bpp->cgid = lpp->cgid;
+ bpp->mode = lpp->mode;
+ bpp->seq = lpp->seq;
+}
+
+
+static void
+bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp)
+{
+ lpp->key = bpp->key;
+ lpp->uid = bpp->uid;
+ lpp->gid = bpp->gid;
+ lpp->cuid = bpp->cuid;
+ lpp->cgid = bpp->cgid;
+ lpp->mode = bpp->mode;
+ lpp->seq = bpp->seq;
+}
+
+struct linux_shmid_ds {
+ struct linux_ipc_perm shm_perm;
+ int shm_segsz;
+ linux_time_t shm_atime;
+ linux_time_t shm_dtime;
+ linux_time_t shm_ctime;
+ ushort shm_cpid;
+ ushort shm_lpid;
+ short shm_nattch;
+ ushort private1;
+ void *private2;
+ void *private3;
+};
+
+static void
+linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
+{
+ linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
+ bsp->shm_segsz = lsp->shm_segsz;
+ bsp->shm_lpid = lsp->shm_lpid;
+ bsp->shm_cpid = lsp->shm_cpid;
+ bsp->shm_nattch = lsp->shm_nattch;
+ bsp->shm_atime = lsp->shm_atime;
+ bsp->shm_dtime = lsp->shm_dtime;
+ bsp->shm_ctime = lsp->shm_ctime;
+ bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */
+}
+
+static void
+bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
+{
+ bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
+ lsp->shm_segsz = bsp->shm_segsz;
+ lsp->shm_lpid = bsp->shm_lpid;
+ lsp->shm_cpid = bsp->shm_cpid;
+ lsp->shm_nattch = bsp->shm_nattch;
+ lsp->shm_atime = bsp->shm_atime;
+ lsp->shm_dtime = bsp->shm_dtime;
+ lsp->shm_ctime = bsp->shm_ctime;
+ lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */
+}
+
+struct linux_ipc_args {
+ int what;
+ int arg1;
+ int arg2;
+ int arg3;
+ caddr_t ptr;
+};
+
+int
+linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmat_args {
+ int shmid;
+ void *shmaddr;
+ int shmflg;
+ } bsd_args;
+ int error;
+
+ bsd_args.shmid = args->arg1;
+ bsd_args.shmaddr = args->ptr;
+ bsd_args.shmflg = args->arg2;
+ if ((error = shmat(p, &bsd_args, retval)))
+ return error;
+ if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int))))
+ return error;
+ retval[0] = 0;
+ return 0;
+}
+
+int
+linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmdt_args {
+ void *shmaddr;
+ } bsd_args;
+
+ bsd_args.shmaddr = args->ptr;
+ return shmdt(p, &bsd_args, retval);
+}
+
+int
+linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmget_args {
+ key_t key;
+ int size;
+ int shmflg;
+ } bsd_args;
+
+ bsd_args.key = args->arg1;
+ bsd_args.size = args->arg2;
+ bsd_args.shmflg = args->arg3;
+ return shmget(p, &bsd_args, retval);
+}
+
+int
+linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmid_ds bsd_shmid;
+ struct linux_shmid_ds linux_shmid;
+ struct shmctl_args {
+ int shmid;
+ int cmd;
+ struct shmid_ds *buf;
+ } bsd_args;
+ int error;
+
+ switch (args->arg2) {
+ case LINUX_IPC_STAT:
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_STAT;
+ bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ if ((error = shmctl(p, &bsd_args, retval)))
+ return error;
+ if ((error = copyin((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
+ sizeof(struct shmid_ds))))
+ return error;
+ bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
+ return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid));
+
+ case LINUX_IPC_SET:
+ if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
+ sizeof(linux_shmid))))
+ return error;
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+ bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
+ sizeof(struct shmid_ds))))
+ return error;
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_SET;
+ return shmctl(p, &bsd_args, retval);
+
+ case LINUX_IPC_RMID:
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_RMID;
+ if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
+ sizeof(linux_shmid))))
+ return error;
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+ bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
+ sizeof(struct shmid_ds))))
+ return error;
+ return shmctl(p, &bsd_args, retval);
+
+ case LINUX_IPC_INFO:
+ case LINUX_SHM_STAT:
+ case LINUX_SHM_INFO:
+ case LINUX_SHM_LOCK:
+ case LINUX_SHM_UNLOCK:
+ default:
+ uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
+ return EINVAL;
+ }
+}
+
+int
+linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ switch (args->what) {
+ case LINUX_SEMOP:
+ return linux_semop(p, args, retval);
+ case LINUX_SEMGET:
+ return linux_semget(p, args, retval);
+ case LINUX_SEMCTL:
+ return linux_semctl(p, args, retval);
+ case LINUX_MSGSND:
+ return linux_msgsnd(p, args, retval);
+ case LINUX_MSGRCV:
+ return linux_msgrcv(p, args, retval);
+ case LINUX_MSGGET:
+ return linux_msgget(p, args, retval);
+ case LINUX_MSGCTL:
+ return linux_msgctl(p, args, retval);
+ case LINUX_SHMAT:
+ return linux_shmat(p, args, retval);
+ case LINUX_SHMDT:
+ return linux_shmdt(p, args, retval);
+ case LINUX_SHMGET:
+ return linux_shmget(p, args, retval);
+ case LINUX_SHMCTL:
+ return linux_shmctl(p, args, retval);
+ default:
+ uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
+ return ENOSYS;
+ }
+}
diff --git a/sys/i386/linux/linux_misc.c b/sys/i386/linux/linux_misc.c
new file mode 100644
index 0000000000000..bf40786e28a8a
--- /dev/null
+++ b/sys/i386/linux/linux_misc.c
@@ -0,0 +1,660 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_misc.c,v 1.4 1995/06/08 13:50:52 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/mman.h>
+#include <sys/proc.h>
+#include <sys/dirent.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/ioctl.h>
+#include <sys/imgact_aout.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/utsname.h>
+#include <sys/vnode.h>
+#include <sys/wait.h>
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+
+struct linux_alarm_args {
+ unsigned int secs;
+};
+
+int
+linux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval)
+{
+ extern struct timeval time;
+ struct itimerval it, old_it;
+ int s;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): alarm(%d)\n", p->p_pid, args->secs);
+#endif
+ it.it_value.tv_sec = (long)args->secs;
+ it.it_value.tv_usec = 0;
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ s = splclock();
+ old_it = p->p_realtimer;
+ if (timerisset(&old_it.it_value))
+ if (timercmp(&old_it.it_value, &time, <))
+ timerclear(&old_it.it_value);
+ else
+ timevalsub(&old_it.it_value, &time);
+ splx(s);
+ if (itimerfix(&it.it_value) || itimerfix(&it.it_interval))
+ return EINVAL;
+ s = splclock();
+ untimeout(realitexpire, (caddr_t)p);
+ if (timerisset(&it.it_value)) {
+ timevaladd(&it.it_value, &time);
+ timeout(realitexpire, (caddr_t)p, hzto(&it.it_value));
+ }
+ p->p_realtimer = it;
+ splx(s);
+ if (old_it.it_value.tv_usec)
+ old_it.it_value.tv_sec++;
+ *retval = old_it.it_value.tv_sec;
+ return 0;
+}
+
+struct linux_brk_args {
+ linux_caddr_t dsend;
+};
+
+int
+linux_brk(struct proc *p, struct linux_brk_args *args, int *retval)
+{
+#if 0
+ struct vmspace *vm = p->p_vmspace;
+ vm_offset_t new, old;
+ int error;
+ extern int swap_pager_full;
+
+ if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr)
+ return EINVAL;
+ if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr)
+ > p->p_rlimit[RLIMIT_DATA].rlim_cur)
+ return ENOMEM;
+
+ old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize);
+ new = round_page((vm_offset_t)args->dsend);
+ *retval = old;
+ if ((new-old) > 0) {
+ if (swap_pager_full)
+ return ENOMEM;
+ error = vm_map_find(&vm->vm_map, NULL, 0, &old, (new-old), FALSE);
+ if (error)
+ return error;
+ vm->vm_dsize += btoc((new-old));
+ *retval = (int)(vm->vm_daddr + ctob(vm->vm_dsize));
+ }
+ return 0;
+#else
+ struct vmspace *vm = p->p_vmspace;
+ vm_offset_t new, old;
+ struct obreak_args {
+ vm_offset_t newsize;
+ } tmp;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): brk(%08x)\n", p->p_pid, args->dsend);
+#endif
+ old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize);
+ new = (vm_offset_t)args->dsend;
+ tmp.newsize = new;
+ if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp, retval))
+ retval[0] = (int)new;
+ else
+ retval[0] = (int)old;
+
+ return 0;
+#endif
+}
+
+struct linux_uselib_args {
+ char *library;
+};
+
+int
+linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
+{
+ struct nameidata ni;
+ struct vnode *vnodep;
+ struct exec *a_out = 0;
+ struct vattr attr;
+ unsigned long vmaddr, virtual_offset, file_offset;
+ unsigned long buffer, bss_size;
+ char *ptr;
+ char path[MAXPATHLEN];
+ const char *prefix = "/compat/linux";
+ size_t sz, len;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, args->library);
+#endif
+
+ for (ptr = path; (*ptr = *prefix) != '\0'; ptr++, prefix++) ;
+ sz = MAXPATHLEN - (ptr - path);
+ if (error = copyinstr(args->library, ptr, sz, &len))
+ return error;
+ if (*ptr != '/')
+ return EINVAL;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, path);
+#endif
+
+ NDINIT(&ni, LOOKUP, FOLLOW, UIO_SYSSPACE, path, p);
+ if (error = namei(&ni))
+ return error;
+
+ vnodep = ni.ni_vp;
+ if (vnodep == NULL)
+ return ENOEXEC;
+
+ if (vnodep->v_writecount)
+ return ETXTBSY;
+
+ if (error = VOP_GETATTR(vnodep, &attr, p->p_ucred, p))
+ return error;
+
+ if ((vnodep->v_mount->mnt_flag & MNT_NOEXEC)
+ || ((attr.va_mode & 0111) == 0)
+ || (attr.va_type != VREG))
+ return ENOEXEC;
+
+ if (attr.va_size == 0)
+ return ENOEXEC;
+
+ if (error = VOP_ACCESS(vnodep, VEXEC, p->p_ucred, p))
+ return error;
+
+ if (error = VOP_OPEN(vnodep, FREAD, p->p_ucred, p))
+ return error;
+
+ error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, 1024,
+ VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vnodep, 0);
+ if (error)
+ return (error);
+
+ /*
+ * Is it a Linux binary ?
+ */
+ if (((a_out->a_magic >> 16) & 0xff) != 0x64)
+ return -1;
+
+ /*
+ * Set file/virtual offset based on a.out variant.
+ */
+ switch ((int)(a_out->a_magic & 0xffff)) {
+ case 0413: /* ZMAGIC */
+ virtual_offset = 0;
+ file_offset = 1024;
+ break;
+ case 0314: /* QMAGIC */
+ virtual_offset = 4096;
+ file_offset = 0;
+ break;
+ default:
+ return (-1);
+ }
+
+ vnodep->v_flag |= VTEXT;
+ bss_size = round_page(a_out->a_bss);
+ /*
+ * Check if file_offset page aligned,.
+ * Currently we cannot handle misalinged file offsets,
+ * and so we read in the entire image (what a waste).
+ */
+ if (file_offset & PGOFSET) {
+#ifdef DEBUG
+printf("uselib: Non page aligned binary %d\n", file_offset);
+#endif
+ /*
+ * Map text+data read/write/execute
+ */
+ vmaddr = virtual_offset + round_page(a_out->a_entry);
+ error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
+ round_page(a_out->a_text + a_out->a_data), FALSE);
+ if (error)
+ return error;
+
+ error = vm_mmap(kernel_map, &buffer,
+ round_page(a_out->a_text + a_out->a_data + file_offset),
+ VM_PROT_READ, VM_PROT_READ, MAP_FILE,
+ (caddr_t)vnodep, trunc_page(file_offset));
+ if (error)
+ return error;
+
+ error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr,
+ a_out->a_text + a_out->a_data);
+ if (error)
+ return error;
+
+ vm_map_remove(kernel_map, trunc_page(vmaddr),
+ round_page(a_out->a_text + a_out->a_data + file_offset));
+
+ error = vm_map_protect(&p->p_vmspace->vm_map, vmaddr,
+ round_page(a_out->a_text + a_out->a_data),
+ VM_PROT_ALL, TRUE);
+ if (error)
+ return error;
+ }
+ else {
+#ifdef DEBUG
+printf("uselib: Page aligned binary %d\n", file_offset);
+#endif
+ vmaddr = virtual_offset + round_page(a_out->a_entry);
+ error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr,
+ a_out->a_text + a_out->a_data,
+ VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED,
+ (caddr_t)vnodep, file_offset);
+ if (error)
+ return (error);
+ }
+#ifdef DEBUG
+printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]);
+#endif
+ if (bss_size != 0) {
+ vmaddr = virtual_offset + round_page(a_out->a_entry) +
+ round_page(a_out->a_text + a_out->a_data);
+ error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
+ bss_size, FALSE);
+ if (error)
+ return error;
+ error = vm_map_protect(&p->p_vmspace->vm_map, vmaddr, bss_size,
+ VM_PROT_ALL, TRUE);
+ if (error)
+ return error;
+ }
+ return 0;
+}
+
+struct linux_select_args {
+ void *ptr;
+};
+
+int
+linux_select(struct proc *p, struct linux_select_args *args, int *retval)
+{
+ struct {
+ int nfds;
+ fd_set *readfds;
+ fd_set *writefds;
+ fd_set *exceptfds;
+ struct timeval *timeout;
+ } linux_args;
+ struct {
+ unsigned int nd;
+ fd_set *in;
+ fd_set *ou;
+ fd_set *ex;
+ struct timeval *tv;
+ } bsd_args;
+ int error;
+
+ if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
+ sizeof(linux_args))))
+ return error;
+#ifdef DEBUG
+ printf("Linux-emul(%d): select(%d, %d, %d, %d, %d)\n",
+ p->p_pid, linux_args.nfds, linux_args.readfds,
+ linux_args.writefds, linux_args.exceptfds,
+ linux_args.timeout);
+#endif
+ bsd_args.nd = linux_args.nfds;
+ bsd_args.in = linux_args.readfds;
+ bsd_args.ou = linux_args.writefds;
+ bsd_args.ex = linux_args.exceptfds;
+ bsd_args.tv = linux_args.timeout;
+ return select(p, &bsd_args, retval);
+}
+
+struct linux_getpgid_args {
+ int pid;
+};
+
+int
+linux_getpgid(struct proc *p, struct linux_getpgid_args *args, int *retval)
+{
+ struct proc *curproc;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): getpgid(%d)\n", p->p_pid, args->pid);
+#endif
+ if (args->pid != p->p_pid) {
+ if (!(curproc = pfind(args->pid)))
+ return ESRCH;
+ }
+ else
+ curproc = p;
+ *retval = curproc->p_pgid;
+ return 0;
+}
+
+int
+linux_fork(struct proc *p, void *args, int *retval)
+{
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): fork()\n", p->p_pid);
+#endif
+ if (error = fork(p, args, retval))
+ return error;
+ if (retval[1] == 1)
+ retval[0] = 0;
+ return 0;
+}
+
+struct linux_mmap_args {
+ void *ptr;
+};
+
+int
+linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval)
+{
+ struct {
+ linux_caddr_t addr;
+ int len;
+ int prot;
+ int flags;
+ int fd;
+ int pos;
+ } linux_args;
+ struct {
+ caddr_t addr;
+ size_t len;
+ int prot;
+ int flags;
+ int fd;
+ long pad;
+ off_t pos;
+ } bsd_args;
+ int error;
+
+ if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
+ sizeof(linux_args))))
+ return error;
+#ifdef DEBUG
+ printf("Linux-emul(%d): mmap(%08x, %d, %d, %08x, %d, %d)\n",
+ p->p_pid, linux_args.addr, linux_args.len, linux_args.prot,
+ linux_args.flags, linux_args.fd, linux_args.pos);
+#endif
+ bsd_args.flags = 0;
+ if (linux_args.flags & LINUX_MAP_SHARED)
+ bsd_args.flags |= MAP_SHARED;
+ if (linux_args.flags & LINUX_MAP_PRIVATE)
+ bsd_args.flags |= MAP_PRIVATE;
+ if (linux_args.flags & LINUX_MAP_FIXED)
+ bsd_args.flags |= MAP_FIXED;
+ if (linux_args.flags & LINUX_MAP_ANON)
+ bsd_args.flags |= MAP_ANON;
+ bsd_args.addr = linux_args.addr;
+ bsd_args.len = linux_args.len;
+ bsd_args.prot = linux_args.prot;
+ bsd_args.fd = linux_args.fd;
+ bsd_args.pos = linux_args.pos;
+ bsd_args.pad = 0;
+ return mmap(p, &bsd_args, retval);
+}
+
+struct linux_pipe_args {
+ int *pipefds;
+};
+
+int
+linux_pipe(struct proc *p, struct linux_pipe_args *args, int *retval)
+{
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): pipe(*)\n", p->p_pid);
+#endif
+ if (error = pipe(p, 0, retval))
+ return error;
+ if (error = copyout(retval, args->pipefds, 2*sizeof(int)))
+ return error;
+ *retval = 0;
+ return 0;
+}
+
+struct linux_time_args {
+ linux_time_t *tm;
+};
+
+int
+linux_time(struct proc *p, struct linux_time_args *args, int *retval)
+{
+ struct timeval tv;
+ linux_time_t tm;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): time(*)\n", p->p_pid);
+#endif
+ microtime(&tv);
+ tm = tv.tv_sec;
+ if (error = copyout(&tm, args->tm, sizeof(linux_time_t)))
+ return error;
+ *retval = tv.tv_sec;
+ return 0;
+}
+
+struct linux_tms {
+ long tms_utime;
+ long tms_stime;
+ long tms_cutime;
+ long tms_cstime;
+};
+
+struct linux_tms_args {
+ char *buf;
+};
+
+int
+linux_times(struct proc *p, struct linux_tms_args *args, int *retval)
+{
+ extern int hz;
+ struct timeval tv;
+ struct linux_tms tms;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): times(*)\n", p->p_pid);
+#endif
+ tms.tms_utime = p->p_uticks;
+ tms.tms_stime = p->p_sticks;
+ tms.tms_cutime = p->p_stats->p_cru.ru_utime.tv_sec * hz +
+ ((p->p_stats->p_cru.ru_utime.tv_usec * hz)/1000000);
+ tms.tms_cstime = p->p_stats->p_cru.ru_stime.tv_sec * hz +
+ ((p->p_stats->p_cru.ru_stime.tv_usec * hz)/1000000);
+ microtime(&tv);
+ *retval = tv.tv_sec * hz + (tv.tv_usec * hz)/1000000;
+ return (copyout((caddr_t)&tms, (caddr_t)args->buf,
+ sizeof(struct linux_tms)));
+}
+
+struct linux_newuname_t {
+ char sysname[65];
+ char nodename[65];
+ char release[65];
+ char version[65];
+ char machine[65];
+ char domainname[65];
+};
+
+struct linux_newuname_args {
+ char *buf;
+};
+
+int
+linux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval)
+{
+ struct linux_newuname_t linux_newuname;
+ extern char ostype[], osrelease[], machine[];
+ extern char hostname[], domainname[];
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newuname(*)\n", p->p_pid);
+#endif
+ bzero(&linux_newuname, sizeof(struct linux_newuname_args));
+ strncpy(linux_newuname.sysname, ostype, 64);
+ strncpy(linux_newuname.nodename, hostname, 64);
+ strncpy(linux_newuname.release, osrelease, 64);
+ strncpy(linux_newuname.version, version, 64);
+ strncpy(linux_newuname.machine, machine, 64);
+ strncpy(linux_newuname.domainname, domainname, 64);
+ return (copyout((caddr_t)&linux_newuname, (caddr_t)args->buf,
+ sizeof(struct linux_newuname_t)));
+}
+
+struct linux_utime_args {
+ char *fname;
+ linux_time_t *timeptr;
+};
+
+int
+linux_utime(struct proc *p, struct linux_utime_args *args, int *retval)
+{
+ struct bsd_utimes_args {
+ char *fname;
+ struct timeval *tptr;
+ } bsdutimes;
+ struct timeval tv;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): utime(%s, *)\n", p->p_pid, args->fname);
+#endif
+ tv.tv_sec = (long)args->timeptr;
+ tv.tv_usec = 0;
+ bsdutimes.tptr = &tv;
+ bsdutimes.fname = args->fname;
+ return utimes(p, &bsdutimes, retval);
+}
+
+struct linux_waitpid_args {
+ int pid;
+ int *status;
+ int options;
+};
+
+int
+linux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval)
+{
+ struct wait4_args {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
+ int compat;
+ } tmp;
+ int error, tmpstat;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): waitpid(%d, *, %d)\n",
+ p->p_pid, args->pid, args->options);
+#endif
+ tmp.pid = args->pid;
+ tmp.status = args->status;
+ tmp.options = args->options;
+ tmp.rusage = NULL;
+ tmp.compat = 0;
+
+ if (error = wait4(p, &tmp, retval))
+ return error;
+ if (error = copyin(args->status, &tmpstat, sizeof(int)))
+ return error;
+ if (WIFSIGNALED(tmpstat))
+ tmpstat = (tmpstat & 0xffffff80) |
+ bsd_to_linux_signal[WTERMSIG(tmpstat)];
+ else if (WIFSTOPPED(tmpstat))
+ tmpstat = (tmpstat & 0xffff00ff) |
+ (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
+ return copyout(&tmpstat, args->status, sizeof(int));
+}
+
+struct linux_wait4_args {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
+};
+
+int
+linux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval)
+{
+ struct wait4_args {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
+ int compat;
+ } tmp;
+ int error, tmpstat;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): wait4(%d, *, %d, *)\n",
+ p->p_pid, args->pid, args->options);
+#endif
+ tmp.pid = args->pid;
+ tmp.status = args->status;
+ tmp.options = args->options;
+ tmp.rusage = args->rusage;
+ tmp.compat = 0;
+
+ if (error = wait4(p, &tmp, retval))
+ return error;
+ if (error = copyin(args->status, &tmpstat, sizeof(int)))
+ return error;
+ if (WIFSIGNALED(tmpstat))
+ tmpstat = (tmpstat & 0xffffff80) |
+ bsd_to_linux_signal[WTERMSIG(tmpstat)];
+ else if (WIFSTOPPED(tmpstat))
+ tmpstat = (tmpstat & 0xffff00ff) |
+ (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
+ return copyout(&tmpstat, args->status, sizeof(int));
+}
diff --git a/sys/i386/linux/linux_signal.c b/sys/i386/linux/linux_signal.c
new file mode 100644
index 0000000000000..528bb62d2aa3b
--- /dev/null
+++ b/sys/i386/linux/linux_signal.c
@@ -0,0 +1,259 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_signal.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/exec.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+
+#include <vm/vm.h>
+
+#include <i386/linux/linux.h>
+
+#define DONTMASK (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD))
+
+static sigset_t
+linux_to_bsd_sigmask(linux_sigset_t mask) {
+ int i;
+ sigset_t new = 0;
+
+ for (i = 1; i <= LINUX_NSIG; i++)
+ if (mask & (1 << i-1))
+ new |= (1 << (linux_to_bsd_signal[i]-1));
+ return new;
+}
+
+static linux_sigset_t
+bsd_to_linux_sigmask(sigset_t mask) {
+ int i;
+ sigset_t new = 0;
+
+ for (i = 1; i <= NSIG; i++)
+ if (mask & (1 << i-1))
+ new |= (1 << (bsd_to_linux_signal[i]-1));
+ return new;
+}
+
+struct linux_sigaction_args {
+ int sig;
+ linux_sigaction_t *nsa;
+ linux_sigaction_t *osa;
+};
+
+int
+linux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval)
+{
+ linux_sigaction_t linux_sa;
+ struct sigaction *nsa = NULL, *osa = NULL, bsd_sa;
+ struct sigaction_args {
+ int sig;
+ struct sigaction *nsa;
+ struct sigaction *osa;
+ } sa;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigaction(%d, *, *)\n", p->p_pid, args->sig);
+#endif
+ if (args->osa)
+ osa = (struct sigaction *)ua_alloc_init(sizeof(struct sigaction));
+
+ if (args->nsa) {
+ nsa = (struct sigaction *)ua_alloc(sizeof(struct sigaction));
+ if (error = copyin(args->nsa, &linux_sa, sizeof(linux_sigaction_t)))
+ return error;
+ bsd_sa.sa_mask = linux_to_bsd_sigmask(linux_sa.sa_mask);
+ bsd_sa.sa_handler = linux_sa.sa_handler;
+ bsd_sa.sa_flags = 0;
+ if (linux_sa.sa_flags & LINUX_SA_NOCLDSTOP)
+ bsd_sa.sa_flags |= SA_NOCLDSTOP;
+ if (linux_sa.sa_flags & LINUX_SA_ONSTACK)
+ bsd_sa.sa_flags |= SA_ONSTACK;
+ if (linux_sa.sa_flags & LINUX_SA_RESTART)
+ bsd_sa.sa_flags |= SA_RESTART;
+ if (error = copyout(&bsd_sa, nsa, sizeof(struct sigaction)))
+ return error;
+ }
+ sa.sig = linux_to_bsd_signal[args->sig];
+ sa.nsa = nsa;
+ sa.osa = osa;
+ if ((error = sigaction(p, &sa, retval)))
+ return error;
+
+ if (args->osa) {
+ if (error = copyin(osa, &bsd_sa, sizeof(struct sigaction)))
+ return error;
+ linux_sa.sa_handler = bsd_sa.sa_handler;
+ linux_sa.sa_restorer = NULL;
+ linux_sa.sa_mask = bsd_to_linux_sigmask(bsd_sa.sa_mask);
+ linux_sa.sa_flags = 0;
+ if (bsd_sa.sa_flags & SA_NOCLDSTOP)
+ linux_sa.sa_flags |= LINUX_SA_NOCLDSTOP;
+ if (bsd_sa.sa_flags & SA_ONSTACK)
+ linux_sa.sa_flags |= LINUX_SA_ONSTACK;
+ if (bsd_sa.sa_flags & SA_RESTART)
+ linux_sa.sa_flags |= LINUX_SA_RESTART;
+ if (error = copyout(&linux_sa, args->osa, sizeof(linux_sigaction_t)))
+ return error;
+ }
+ return 0;
+}
+
+struct linux_sigprocmask_args {
+ int how;
+ linux_sigset_t *mask;
+ linux_sigset_t *omask;
+};
+
+int
+linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args,
+ int *retval)
+{
+ int error, s;
+ sigset_t mask;
+ sigset_t omask;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how);
+#endif
+ if (args->omask != NULL) {
+ omask = bsd_to_linux_sigmask(p->p_sigmask);
+ if (error = copyout(&omask, args->omask, sizeof(sigset_t)))
+ return error;
+ }
+ if (!(args->mask))
+ return 0;
+ if (error = copyin(args->mask, &mask, sizeof(linux_sigset_t)))
+ return error;
+
+ mask = linux_to_bsd_sigmask(mask);
+ s = splhigh();
+ switch (args->how) {
+ case LINUX_SIG_BLOCK:
+ p->p_sigmask |= (mask & ~DONTMASK);
+ break;
+ case LINUX_SIG_UNBLOCK:
+ p->p_sigmask &= ~mask;
+ break;
+ case LINUX_SIG_SETMASK:
+ p->p_sigmask = (mask & ~DONTMASK);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ splx(s);
+ return error;
+}
+
+int
+linux_siggetmask(struct proc *p, void *args, int *retval)
+{
+#ifdef DEBUG
+ printf("Linux-emul(%d): siggetmask()\n", p->p_pid);
+#endif
+ *retval = bsd_to_linux_sigmask(p->p_sigmask);
+ return 0;
+}
+
+struct linux_sigsetmask_args {
+ linux_sigset_t mask;
+};
+
+int
+linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args,int *retval)
+{
+ int s;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigsetmask(%08x)\n", p->p_pid, args->mask);
+#endif
+ s = splhigh();
+ p->p_sigmask = (linux_to_bsd_sigmask(args->mask) & ~DONTMASK);
+ splx(s);
+ *retval = bsd_to_linux_sigmask(p->p_sigmask);
+ return 0;
+}
+
+struct linux_sigpending_args {
+ linux_sigset_t *mask;
+};
+
+int
+linux_sigpending(struct proc *p, struct linux_sigpending_args *args,int *retval)
+{
+ linux_sigset_t linux_sig;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigpending(*)\n", p->p_pid);
+#endif
+ linux_sig = bsd_to_linux_sigmask(p->p_siglist & p->p_sigmask);
+ return copyout(&linux_sig, args->mask, sizeof(linux_sig));
+}
+
+struct linux_sigsuspend_args {
+ linux_sigset_t mask;
+};
+
+int
+linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args,int *retval)
+{
+ sigset_t tmp;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigsuspend(%08x)\n", p->p_pid, args->mask);
+#endif
+ tmp = linux_to_bsd_sigmask(args->mask);
+ return sigsuspend(p, &tmp , retval);
+}
+
+struct linux_kill_args {
+ int pid;
+ int signum;
+};
+
+int
+linux_kill(struct proc *p, struct linux_kill_args *args, int *retval)
+{
+ struct {
+ int pid;
+ int signum;
+ } tmp;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): kill(%d, %d)\n",
+ p->p_pid, args->pid, args->signum);
+#endif
+ tmp.pid = args->pid;
+ tmp.signum = linux_to_bsd_signal[args->signum];
+ return kill(p, &tmp, retval);
+}
diff --git a/sys/i386/linux/linux_socket.c b/sys/i386/linux/linux_socket.c
new file mode 100644
index 0000000000000..9267063a7f7e1
--- /dev/null
+++ b/sys/i386/linux/linux_socket.c
@@ -0,0 +1,595 @@
+/*-
+ * Copyright (c) 1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_socket.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <netinet/in.h>
+
+
+static int
+linux_to_bsd_domain(int domain)
+{
+ switch (domain) {
+ case LINUX_AF_UNSPEC:
+ return AF_UNSPEC;
+ case LINUX_AF_UNIX:
+ return AF_LOCAL;
+ case LINUX_AF_INET:
+ return AF_INET;
+ case LINUX_AF_AX25:
+ return AF_CCITT;
+ case LINUX_AF_IPX:
+ return AF_IPX;
+ case LINUX_AF_APPLETALK:
+ return AF_APPLETALK;
+ default:
+ return -1;
+ }
+}
+
+static int
+linux_to_bsd_sockopt_level(int level)
+{
+ switch (level) {
+ case LINUX_SOL_SOCKET:
+ return SOL_SOCKET;
+ default:
+ return level;
+ }
+}
+
+static int linux_to_bsd_ip_sockopt(int opt)
+{
+ switch (opt) {
+ case LINUX_IP_TOS:
+ return IP_TOS;
+ case LINUX_IP_TTL:
+ return IP_TTL;
+ default:
+ return -1;
+ }
+}
+
+static int
+linux_to_bsd_so_sockopt(int opt)
+{
+ switch (opt) {
+ case LINUX_SO_DEBUG:
+ return SO_DEBUG;
+ case LINUX_SO_REUSEADDR:
+ return SO_REUSEADDR;
+ case LINUX_SO_TYPE:
+ return SO_TYPE;
+ case LINUX_SO_ERROR:
+ return SO_ERROR;
+ case LINUX_SO_DONTROUTE:
+ return SO_DONTROUTE;
+ case LINUX_SO_BROADCAST:
+ return SO_BROADCAST;
+ case LINUX_SO_SNDBUF:
+ return SO_SNDBUF;
+ case LINUX_SO_RCVBUF:
+ return SO_RCVBUF;
+ case LINUX_SO_KEEPALIVE:
+ return SO_KEEPALIVE;
+ case LINUX_SO_OOBINLINE:
+ return SO_OOBINLINE;
+ case LINUX_SO_LINGER:
+ return SO_LINGER;
+ case LINUX_SO_PRIORITY:
+ case LINUX_SO_NO_CHECK:
+ default:
+ return -1;
+ }
+}
+
+struct linux_socket_args {
+ int domain;
+ int type;
+ int protocol;
+};
+
+static int
+linux_socket(struct proc *p, struct linux_socket_args *args, int *retval)
+{
+ struct linux_socket_args linux_args;
+ struct {
+ int domain;
+ int type;
+ int protocol;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.protocol = linux_args.protocol;
+ bsd_args.type = linux_args.type;
+ bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
+ if (bsd_args.domain == -1)
+ return EINVAL;
+ return socket(p, &bsd_args, retval);
+}
+
+struct linux_bind_args {
+ int s;
+ struct sockaddr *name;
+ int namelen;
+};
+
+static int
+linux_bind(struct proc *p, struct linux_bind_args *args, int *retval)
+{
+ struct linux_bind_args linux_args;
+ struct {
+ int s;
+ caddr_t name;
+ int namelen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.name;
+ bsd_args.namelen = linux_args.namelen;
+ return bind(p, &bsd_args, retval);
+}
+
+struct linux_connect_args {
+ int s;
+ struct sockaddr * name;
+ int namelen;
+};
+
+static int
+linux_connect(struct proc *p, struct linux_connect_args *args, int *retval)
+{
+ struct linux_connect_args linux_args;
+ struct {
+ int s;
+ caddr_t name;
+ int namelen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.name;
+ bsd_args.namelen = linux_args.namelen;
+ return connect(p, &bsd_args, retval);
+}
+
+struct linux_listen_args {
+ int s;
+ int backlog;
+};
+
+static int
+linux_listen(struct proc *p, struct linux_listen_args *args, int *retval)
+{
+ struct linux_listen_args linux_args;
+ struct {
+ int s;
+ int backlog;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.backlog = linux_args.backlog;
+ return listen(p, &bsd_args, retval);
+}
+
+struct linux_accept_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_accept(struct proc *p, struct linux_accept_args *args, int *retval)
+{
+ struct linux_accept_args linux_args;
+ struct accept_args {
+ int s;
+ caddr_t name;
+ int *anamelen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.addr;
+ bsd_args.anamelen = linux_args.namelen;
+ return oaccept(p, &bsd_args, retval);
+}
+
+struct linux_getsockname_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_getsockname(struct proc *p, struct linux_getsockname_args *args, int *retval)
+{
+ struct linux_getsockname_args linux_args;
+ struct {
+ int fdes;
+ caddr_t asa;
+ int *alen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.fdes = linux_args.s;
+ bsd_args.asa = (caddr_t) linux_args.addr;
+ bsd_args.alen = linux_args.namelen;
+ return ogetsockname(p, &bsd_args, retval);
+}
+
+struct linux_getpeername_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_getpeername(struct proc *p, struct linux_getpeername_args *args, int *retval)
+{
+ struct linux_getpeername_args linux_args;
+ struct getpeername_args {
+ int fdes;
+ caddr_t asa;
+ int *alen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.fdes = linux_args.s;
+ bsd_args.asa = (caddr_t) linux_args.addr;
+ bsd_args.alen = linux_args.namelen;
+ return ogetpeername(p, &bsd_args, retval);
+}
+
+struct linux_socketpair_args {
+ int domain;
+ int type;
+ int protocol;
+ int *rsv;
+};
+
+static int
+linux_socketpair(struct proc *p, struct linux_socketpair_args *args, int *retval)
+{
+ struct linux_socketpair_args linux_args;
+ struct {
+ int domain;
+ int type;
+ int protocol;
+ int *rsv;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
+ if (bsd_args.domain == -1)
+ return EINVAL;
+ bsd_args.type = linux_args.type;
+ bsd_args.protocol = linux_args.protocol;
+ bsd_args.rsv = linux_args.rsv;
+ return socketpair(p, &bsd_args, retval);
+}
+
+struct linux_send_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+};
+
+static int
+linux_send(struct proc *p, struct linux_send_args *args, int *retval)
+{
+ struct linux_send_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ return osend(p, &bsd_args, retval);
+}
+
+struct linux_recv_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+};
+
+static int
+linux_recv(struct proc *p, struct linux_recv_args *args, int *retval)
+{
+ struct linux_recv_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ return orecv(p, &bsd_args, retval);
+}
+
+struct linux_sendto_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+ caddr_t to;
+ int tolen;
+};
+
+static int
+linux_sendto(struct proc *p, struct linux_sendto_args *args, int *retval)
+{
+ struct linux_sendto_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ size_t len;
+ int flags;
+ caddr_t to;
+ int tolen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ bsd_args.to = linux_args.to;
+ bsd_args.tolen = linux_args.tolen;
+ return sendto(p, &bsd_args, retval);
+}
+
+struct linux_recvfrom_args {
+ int s;
+ void *buf;
+ int len;
+ int flags;
+ caddr_t from;
+ int *fromlen;
+};
+
+static int
+linux_recvfrom(struct proc *p, struct linux_recvfrom_args *args, int *retval)
+{
+ struct linux_recvfrom_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ size_t len;
+ int flags;
+ caddr_t from;
+ int *fromlenaddr;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.buf;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ bsd_args.from = linux_args.from;
+ bsd_args.fromlenaddr = linux_args.fromlen;
+ return orecvfrom(p, &bsd_args, retval);
+}
+
+struct linux_shutdown_args {
+ int s;
+ int how;
+};
+
+static int
+linux_shutdown(struct proc *p, struct linux_shutdown_args *args, int *retval)
+{
+ struct linux_shutdown_args linux_args;
+ struct {
+ int s;
+ int how;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.how = linux_args.how;
+ return shutdown(p, &bsd_args, retval);
+}
+
+struct linux_setsockopt_args {
+ int s;
+ int level;
+ int optname;
+ void *optval;
+ int optlen;
+};
+
+static int
+linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args, int *retval)
+{
+ struct linux_setsockopt_args linux_args;
+ struct {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int valsize;
+ } bsd_args;
+ int error, name;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
+ switch (bsd_args.level) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(linux_args.optname);
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(linux_args.optname);
+ break;
+ default:
+ return EINVAL;
+ }
+ if (name == -1)
+ return EINVAL;
+ bsd_args.name = name;
+ bsd_args.val = linux_args.optval;
+ bsd_args.valsize = linux_args.optlen;
+ return setsockopt(p, &bsd_args, retval);
+}
+
+struct linux_getsockopt_args {
+ int s;
+ int level;
+ int optname;
+ void *optval;
+ int *optlen;
+};
+
+static int
+linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args, int *retval)
+{
+ struct linux_getsockopt_args linux_args;
+ struct {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int *avalsize;
+ } bsd_args;
+ int error, name;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
+ switch (bsd_args.level) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(linux_args.optname);
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(linux_args.optname);
+ break;
+ default:
+ return EINVAL;
+ }
+ if (name == -1)
+ return EINVAL;
+ bsd_args.val = linux_args.optval;
+ bsd_args.avalsize = linux_args.optlen;
+ return getsockopt(p, &bsd_args, retval);
+}
+
+struct linux_socketcall_args {
+ int what;
+ void *args;
+};
+
+int
+linux_socketcall(struct proc *p, struct linux_socketcall_args *args,int *retval)
+{
+ switch (args->what) {
+ case LINUX_SOCKET:
+ return linux_socket(p, args->args, retval);
+ case LINUX_BIND:
+ return linux_bind(p, args->args, retval);
+ case LINUX_CONNECT:
+ return linux_connect(p, args->args, retval);
+ case LINUX_LISTEN:
+ return linux_listen(p, args->args, retval);
+ case LINUX_ACCEPT:
+ return linux_accept(p, args->args, retval);
+ case LINUX_GETSOCKNAME:
+ return linux_getsockname(p, args->args, retval);
+ case LINUX_GETPEERNAME:
+ return linux_getpeername(p, args->args, retval);
+ case LINUX_SOCKETPAIR:
+ return linux_socketpair(p, args->args, retval);
+ case LINUX_SEND:
+ return linux_send(p, args->args, retval);
+ case LINUX_RECV:
+ return linux_recv(p, args->args, retval);
+ case LINUX_SENDTO:
+ return linux_sendto(p, args->args, retval);
+ case LINUX_RECVFROM:
+ return linux_recvfrom(p, args->args, retval);
+ case LINUX_SHUTDOWN:
+ return linux_shutdown(p, args->args, retval);
+ case LINUX_SETSOCKOPT:
+ return linux_setsockopt(p, args->args, retval);
+ case LINUX_GETSOCKOPT:
+ return linux_getsockopt(p, args->args, retval);
+ default:
+ uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
+ return ENOSYS;
+ }
+}
diff --git a/sys/i386/linux/linux_stats.c b/sys/i386/linux/linux_stats.c
new file mode 100644
index 0000000000000..1dbfcf11e64bf
--- /dev/null
+++ b/sys/i386/linux/linux_stats.c
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_stats.c,v 1.3 1995/06/08 13:50:52 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/dirent.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/stat.h>
+#include <sys/vnode.h>
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+
+#include <i386/linux/linux.h>
+
+struct linux_newstat {
+ unsigned short stat_dev;
+ unsigned short __pad1;
+ unsigned long stat_ino;
+ unsigned short stat_mode;
+ unsigned short stat_nlink;
+ unsigned short stat_uid;
+ unsigned short stat_gid;
+ unsigned short stat_rdev;
+ unsigned short __pad2;
+ unsigned long stat_size;
+ unsigned long stat_blksize;
+ unsigned long stat_blocks;
+ unsigned long stat_atime;
+ unsigned long __unused1;
+ unsigned long stat_mtime;
+ unsigned long __unused2;
+ unsigned long stat_ctime;
+ unsigned long __unused3;
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+struct linux_newstat_args {
+ char *path;
+ struct linux_newstat *buf;
+};
+
+static int
+newstat_copyout(struct stat *buf, void *ubuf)
+{
+ struct linux_newstat tbuf;
+
+ tbuf.stat_dev = (buf->st_dev & 0xff) | ((buf->st_dev & 0xff00)<<10);
+ tbuf.stat_ino = buf->st_ino;
+ tbuf.stat_mode = buf->st_mode;
+ tbuf.stat_nlink = buf->st_nlink;
+ tbuf.stat_uid = buf->st_uid;
+ tbuf.stat_gid = buf->st_gid;
+ tbuf.stat_rdev = buf->st_rdev;
+ tbuf.stat_size = buf->st_size;
+ tbuf.stat_atime = buf->st_atime;
+ tbuf.stat_mtime = buf->st_mtime;
+ tbuf.stat_ctime = buf->st_ctime;
+ tbuf.stat_blksize = buf->st_blksize;
+ tbuf.stat_blocks = buf->st_blocks;
+ return copyout(&tbuf, ubuf, sizeof(tbuf));
+}
+
+int
+linux_newstat(struct proc *p, struct linux_newstat_args *args, int *retval)
+{
+ struct stat buf;
+ struct linux_newstat tbuf;
+ struct nameidata nd;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newstat(%s, *)\n", p->p_pid, args->path);
+#endif
+ NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_USERSPACE, args->path, p);
+ error = namei(&nd);
+ if (!error) {
+ error = vn_stat(nd.ni_vp, &buf, p);
+ vput(nd.ni_vp);
+ }
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+ return error;
+}
+
+int
+linux_newlstat(struct proc *p, struct linux_newstat_args *args, int *retval)
+{
+ struct stat buf;
+ struct linux_newstat tbuf;
+ struct nameidata nd;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newlstat(%s, *)\n", p->p_pid, args->path);
+#endif
+ NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_USERSPACE, args->path, p);
+ error = namei(&nd);
+ if (!error) {
+ error = vn_stat(nd.ni_vp, &buf, p);
+ vput(nd.ni_vp);
+ }
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+ return error;
+}
+
+struct linux_newfstat_args {
+ int fd;
+ struct linux_newstat *buf;
+};
+
+int
+linux_newfstat(struct proc *p, struct linux_newfstat_args *args, int *retval)
+{
+ struct linux_newstat tbuf;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ struct stat buf;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newlstat(%d, *)\n", p->p_pid, args->fd);
+#endif
+ if ((unsigned)args->fd >= fdp->fd_nfiles
+ || (fp = fdp->fd_ofiles[args->fd]) == NULL)
+ return EBADF;
+ switch (fp->f_type) {
+ case DTYPE_VNODE:
+ error = vn_stat((struct vnode *)fp->f_data, &buf, p);
+ break;
+ case DTYPE_SOCKET:
+ error = soo_stat((struct socket *)fp->f_data, &buf);
+ break;
+ default:
+ panic("LINUX newfstat");
+ }
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+ return error;
+}
+
+struct linux_statfs {
+ long ftype;
+ long fbsize;
+ long fblocks;
+ long fbfree;
+ long fbavail;
+ long ffiles;
+ long fffree;
+ linux_fsid_t ffsid;
+ long fnamelen;
+ long fspare[6];
+};
+
+
+struct linux_statfs_args {
+ char *path;
+ struct statfs *buf;
+};
+
+int
+linux_statfs(struct proc *p, struct linux_statfs_args *args, int *retval)
+{
+ struct mount *mp;
+ struct nameidata *ndp;
+ struct statfs *bsd_statfs;
+ struct nameidata nd;
+ struct linux_statfs linux_statfs;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): statfs(%s, *)\n", p->p_pid, args->path);
+#endif
+ ndp = &nd;
+ ndp->ni_cnd.cn_nameiop = LOOKUP;
+ ndp->ni_cnd.cn_flags = FOLLOW;
+ ndp->ni_cnd.cn_proc = curproc;
+ ndp->ni_cnd.cn_cred = curproc->p_cred->pc_ucred;
+ ndp->ni_segflg = UIO_USERSPACE;
+ ndp->ni_dirp = args->path;
+ if (error = namei(ndp))
+ return error;
+ mp = ndp->ni_vp->v_mount;
+ bsd_statfs = &mp->mnt_stat;
+ vrele(ndp->ni_vp);
+ if (error = VFS_STATFS(mp, bsd_statfs, p))
+ return error;
+ bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ linux_statfs.ftype = bsd_statfs->f_type;
+ linux_statfs.fbsize = bsd_statfs->f_bsize;
+ linux_statfs.fblocks = bsd_statfs->f_blocks;
+ linux_statfs.fbfree = bsd_statfs->f_bfree;
+ linux_statfs.fbavail = bsd_statfs->f_bavail;
+ linux_statfs.fffree = bsd_statfs->f_ffree;
+ linux_statfs.ffiles = bsd_statfs->f_files;
+ linux_statfs.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs.fnamelen = MAXNAMLEN;
+ return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
+ sizeof(struct linux_statfs));
+}
+
+struct linux_fstatfs_args {
+ int fd;
+ struct statfs *buf;
+};
+
+int
+linux_fstatfs(struct proc *p, struct linux_fstatfs_args *args, int *retval)
+{
+ struct file *fp;
+ struct mount *mp;
+ struct statfs *bsd_statfs;
+ struct linux_statfs linux_statfs;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): fstatfs(%d, *)\n", p->p_pid, args->fd);
+#endif
+ if (error = getvnode(p->p_fd, args->fd, &fp))
+ return error;
+ mp = ((struct vnode *)fp->f_data)->v_mount;
+ bsd_statfs = &mp->mnt_stat;
+ if (error = VFS_STATFS(mp, bsd_statfs, p))
+ return error;
+ bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ linux_statfs.ftype = bsd_statfs->f_type;
+ linux_statfs.fbsize = bsd_statfs->f_bsize;
+ linux_statfs.fblocks = bsd_statfs->f_blocks;
+ linux_statfs.fbfree = bsd_statfs->f_bfree;
+ linux_statfs.fbavail = bsd_statfs->f_bavail;
+ linux_statfs.fffree = bsd_statfs->f_ffree;
+ linux_statfs.ffiles = bsd_statfs->f_files;
+ linux_statfs.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs.fnamelen = MAXNAMLEN;
+ return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
+ sizeof(struct linux_statfs));
+}
diff --git a/sys/i386/linux/linux_sysent.c b/sys/i386/linux/linux_sysent.c
new file mode 100644
index 0000000000000..015d49a6d9499
--- /dev/null
+++ b/sys/i386/linux/linux_sysent.c
@@ -0,0 +1,367 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_sysent.c,v 1.3 1995/06/08 13:50:52 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysent.h>
+#include <sys/imgact.h>
+#include <sys/errno.h>
+#include <sys/signal.h>
+
+extern int access();
+extern int acct();
+extern int linux_adjtimex();
+extern int linux_alarm();
+extern int linux_bdflush();
+extern int linux_break();
+extern int linux_brk();
+extern int chdir();
+extern int chmod();
+extern int chown();
+extern int chroot();
+extern int linux_clone();
+extern int close();
+extern int linux_creat();
+extern int linux_create_module();
+extern int linux_delete_module();
+extern int dup();
+extern int dup2();
+extern int execve();
+extern int exit();
+extern int fchdir();
+extern int fchmod();
+extern int fchown();
+extern int linux_fcntl();
+extern int linux_fork();
+extern int linux_fstat();
+extern int linux_fstatfs();
+extern int fsync();
+extern int linux_ftime();
+extern int oftruncate();
+extern int linux_get_kernel_syms();
+extern int getegid();
+extern int geteuid();
+extern int getgid();
+extern int getgroups();
+extern int getitimer();
+extern int linux_getpgid();
+extern int getpgrp();
+extern int getpid();
+extern int getppid();
+extern int getpriority();
+extern int ogetrlimit();
+extern int getrusage();
+extern int gettimeofday();
+extern int getuid();
+extern int linux_gtty();
+extern int linux_idle();
+extern int linux_init_module();
+extern int linux_ioctl();
+extern int linux_ioperm();
+extern int linux_iopl();
+extern int linux_ipc();
+extern int linux_kill();
+extern int link();
+extern int linux_lock();
+extern int linux_lseek();
+extern int ostat();
+extern int mkdir();
+extern int mknod();
+extern int linux_mmap();
+extern int linux_modify_ldt();
+extern int linux_mount();
+extern int mprotect();
+extern int linux_mpx();
+extern int munmap();
+extern int linux_newfstat();
+extern int linux_newlstat();
+extern int linux_newstat();
+extern int linux_newuname();
+extern int linux_nice();
+extern int linux_olduname();
+extern int linux_open();
+extern int linux_pause();
+extern int linux_phys();
+extern int linux_pipe();
+extern int linux_prof();
+extern int profil();
+extern int linux_ptrace();
+extern int linux_quotactl();
+extern int read();
+extern int linux_readdir();
+extern int readlink();
+extern int reboot();
+extern int rename();
+extern int rmdir();
+extern int linux_select();
+extern int setdomainname();
+extern int setgid();
+extern int setgroups();
+extern int osethostname();
+extern int setitimer();
+extern int setpgid();
+extern int setpriority();
+extern int setregid();
+extern int setreuid();
+extern int osetrlimit();
+extern int setsid();
+extern int settimeofday();
+extern int setuid();
+extern int sigreturn();
+extern int linux_setup();
+extern int linux_sigaction();
+extern int linux_siggetmask();
+extern int linux_signal();
+extern int linux_sigpending();
+extern int linux_sigprocmask();
+extern int linux_sigreturn();
+extern int linux_sigsetmask();
+extern int linux_sigsuspend();
+extern int linux_socketcall();
+extern int linux_stat();
+extern int linux_statfs();
+extern int linux_stime();
+extern int linux_stty();
+extern int linux_swapoff();
+extern int swapon();
+extern int symlink();
+extern int sync();
+extern int linux_sysinfo();
+extern int linux_syslog();
+extern int linux_time();
+extern int linux_times();
+extern int otruncate();
+extern int linux_ulimit();
+extern int umask();
+extern int linux_umount();
+extern int linux_uname();
+extern int unlink();
+extern int linux_uselib();
+extern int linux_ustat();
+extern int linux_utime();
+extern int linux_vhangup();
+extern int linux_vm86();
+extern int linux_wait4();
+extern int linux_waitpid();
+extern int write();
+
+static struct sysent linux_sysent[] = {
+ 0, linux_setup, /* 0 */
+ 1, exit, /* 1 */
+ 0, linux_fork, /* 2 */
+ 3, read, /* 3 */
+ 3, write, /* 4 */
+ 3, linux_open, /* 5 */
+ 1, close, /* 6 */
+ 3, linux_waitpid, /* 7 */
+ 2, linux_creat, /* 8 */
+ 2, link, /* 9 */
+ 1, unlink, /* 10 */
+ 3, execve, /* 11 */
+ 1, chdir, /* 12 */
+ 1, linux_time, /* 13 */
+ 3, mknod, /* 14 */
+ 2, chmod, /* 15 */
+ 3, chown, /* 16 */
+ 1, linux_break, /* 17 */
+ 2, linux_stat, /* 18 */
+ 3, linux_lseek, /* 19 */
+ 0, getpid, /* 20 */
+ 5, linux_mount, /* 21 */
+ 1, linux_umount, /* 22 */
+ 1, setuid, /* 23 */
+ 0, getuid, /* 24 */
+ 1, linux_stime, /* 25 */
+ 4, linux_ptrace, /* 26 */
+ 1, linux_alarm, /* 27 */
+ 2, linux_fstat, /* 28 */
+ 0, linux_pause, /* 29 */
+ 2, linux_utime, /* 30 */
+ 0, linux_stty, /* 31 */
+ 0, linux_gtty, /* 32 */
+ 2, access, /* 33 */
+ 1, linux_nice, /* 34 */
+ 0, linux_ftime, /* 35 */
+ 0, sync, /* 36 */
+ 2, linux_kill, /* 37 */
+ 2, rename, /* 38 */
+ 2, mkdir, /* 39 */
+ 1, rmdir, /* 40 */
+ 1, dup, /* 41 */
+ 1, linux_pipe, /* 42 */
+ 1, linux_times, /* 43 */
+ 0, linux_prof, /* 44 */
+ 1, linux_brk, /* 45 */
+ 1, setgid, /* 46 */
+ 0, getgid, /* 47 */
+ 2, linux_signal, /* 48 */
+ 0, geteuid, /* 49 */
+ 0, getegid, /* 50 */
+ 0, acct, /* 51 */
+ 0, linux_phys, /* 52 */
+ 0, linux_lock, /* 53 */
+ 3, linux_ioctl, /* 54 */
+ 3, linux_fcntl, /* 55 */
+ 0, linux_mpx, /* 56 */
+ 2, setpgid, /* 57 */
+ 0, linux_ulimit, /* 58 */
+ 1, linux_olduname, /* 59 */
+ 1, umask, /* 60 */
+ 1, chroot, /* 61 */
+ 2, linux_ustat, /* 62 */
+ 2, dup2, /* 63 */
+ 0, getppid, /* 64 */
+ 0, getpgrp, /* 65 */
+ 0, setsid, /* 66 */
+ 3, linux_sigaction, /* 67 */
+ 0, linux_siggetmask, /* 68 */
+ 1, linux_sigsetmask, /* 69 */
+ 2, setreuid, /* 70 */
+ 2, setregid, /* 71 */
+ 1, linux_sigsuspend, /* 72 */
+ 1, linux_sigpending, /* 73 */
+ 2, osethostname, /* 74 */
+ 2, osetrlimit, /* 75 */
+ 2, ogetrlimit, /* 76 */
+ 2, getrusage, /* 77 */
+ 2, gettimeofday, /* 78 */
+ 2, settimeofday, /* 79 */
+ 2, getgroups, /* 80 */
+ 2, setgroups, /* 81 */
+ 1, linux_select, /* 82 */
+ 2, symlink, /* 83 */
+ 2, ostat, /* 84 */
+ 3, readlink, /* 85 */
+ 1, linux_uselib, /* 86 */
+ 1, swapon, /* 87 */
+ 3, reboot, /* 88 */
+ 3, linux_readdir, /* 89 */
+ 1, linux_mmap, /* 90 */
+ 2, munmap, /* 91 */
+ 2, otruncate, /* 92 */
+ 2, oftruncate, /* 93 */
+ 2, fchmod, /* 94 */
+ 3, fchown, /* 95 */
+ 2, getpriority, /* 96 */
+ 3, setpriority, /* 97 */
+ 0, profil, /* 98 */
+ 2, linux_statfs, /* 99 */
+ 2, linux_fstatfs, /* 100 */
+ 3, linux_ioperm, /* 101 */
+ 2, linux_socketcall, /* 102 */
+ 3, linux_syslog, /* 103 */
+ 3, setitimer, /* 104 */
+ 2, getitimer, /* 105 */
+ 2, linux_newstat, /* 106 */
+ 2, linux_newlstat, /* 107 */
+ 2, linux_newfstat, /* 108 */
+ 2, linux_uname, /* 109 */
+ 1, linux_iopl, /* 110 */
+ 0, linux_vhangup, /* 111 */
+ 0, linux_idle, /* 112 */
+ 1, linux_vm86, /* 113 */
+ 4, linux_wait4, /* 114 */
+ 1, linux_swapoff, /* 115 */
+ 1, linux_sysinfo, /* 116 */
+ 4, linux_ipc, /* 117 */
+ 1, fsync, /* 118 */
+ 1, linux_sigreturn, /* 119 */
+ 0, linux_clone, /* 120 */
+ 2, setdomainname, /* 121 */
+ 1, linux_newuname, /* 122 */
+ 3, linux_modify_ldt, /* 123 */
+ 1, linux_adjtimex, /* 124 */
+ 3, mprotect, /* 125 */
+ 3, linux_sigprocmask, /* 126 */
+ 2, linux_create_module, /* 127 */
+ 4, linux_init_module, /* 128 */
+ 1, linux_delete_module, /* 129 */
+ 1, linux_get_kernel_syms, /* 130 */
+ 0, linux_quotactl, /* 131 */
+ 1, linux_getpgid, /* 132 */
+ 1, fchdir, /* 133 */
+ 0, linux_bdflush, /* 134 */
+};
+
+int bsd_to_linux_errno[ELAST] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 35, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 11,115,114, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100,101,102,103,104,105,106,107,108,109,
+ 110,111, 40, 36,112,113, 39, 11, 87,122,
+ 116, 66, 6, 6, 6, 6, 6, 37, 38, 9,
+ 6,
+};
+
+int bsd_to_linux_signal[NSIG] = {
+ 0, LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT,
+ LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0,
+ LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV,
+ 0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM,
+ LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT,
+ LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO,
+ LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF,
+ LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2
+};
+
+int linux_to_bsd_signal[LINUX_NSIG] = {
+ 0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT,
+ SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM,
+ SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO,
+ SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0
+};
+
+int linux_fixup(int **stack_base, struct image_params *iparams)
+{
+ int *argv, *envp;
+
+ argv = *stack_base;
+ envp = *stack_base + (iparams->argc + 1);
+ (*stack_base)--;
+ **stack_base = (int)envp;
+ (*stack_base)--;
+ **stack_base = (int)argv;
+ (*stack_base)--;
+ **stack_base = (int)iparams->argc;
+}
+
+struct sysentvec linux_sysvec = {
+ sizeof (linux_sysent) / sizeof(linux_sysent[0]),
+ linux_sysent,
+ 0xff,
+ NSIG,
+ bsd_to_linux_signal,
+ ELAST,
+ bsd_to_linux_errno,
+ linux_fixup
+};
diff --git a/sys/i386/scsi/93cx6.c b/sys/i386/scsi/93cx6.c
new file mode 100644
index 0000000000000..280af0c556aae
--- /dev/null
+++ b/sys/i386/scsi/93cx6.c
@@ -0,0 +1,175 @@
+/*
+ * Interface for the 93C46/26/06 serial eeprom parts.
+ *
+ * Copyright (c) 1995 Daniel M. Eischen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Absolutely no warranty of function or purpose is made by the author
+ * Daniel M. Eischen.
+ * 4. Modifications may be freely made to this file if the above conditions
+ * are met.
+ *
+ * $Id$
+ */
+
+/*
+ * The instruction set of the 93C46/26/06 chips are as follows:
+ *
+ * Start OP
+ * Function Bit Code Address Data Description
+ * -------------------------------------------------------------------
+ * READ 1 10 A5 - A0 Reads data stored in memory,
+ * starting at specified address
+ * EWEN 1 00 11XXXX Write enable must preceed
+ * all programming modes
+ * ERASE 1 11 A5 - A0 Erase register A5A4A3A2A1A0
+ * WRITE 1 01 A5 - A0 D15 - D0 Writes register
+ * ERAL 1 00 10XXXX Erase all registers
+ * WRAL 1 00 01XXXX D15 - D0 Writes to all registers
+ * EWDS 1 00 00XXXX Disables all programming
+ * instructions
+ * *Note: A value of X for address is a don't care condition.
+ *
+ * The 93C46 has a four wire interface: clock, chip select, data in, and
+ * data out. In order to perform one of the above functions, you need
+ * to enable the chip select for a clock period (typically a minimum of
+ * 1 usec, with the clock high and low a minimum of 750 and 250 nsec
+ * respectively. While the chip select remains high, you can clock in
+ * the instructions (above) starting with the start bit, followed by the
+ * OP code, Address, and Data (if needed). For the READ instruction, the
+ * requested 16-bit register contents is read from the data out line but
+ * is preceded by an initial zero (leading 0, followed by 16-bits, MSB
+ * first). The clock cycling from low to high initiates the next data
+ * bit to be sent from the chip.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <machine/clock.h>
+#include <i386/scsi/93cx6.h>
+
+/*
+ * Right now, we only have to read the SEEPROM. But we make it easier to
+ * add other 93Cx6 functions.
+ */
+struct seeprom_cmd {
+ unsigned char len;
+ unsigned char bits[3];
+} seeprom_read = {3, {1, 1, 0}};
+
+
+/*
+ * Wait for the SEERDY to go high; about 800 ns.
+ */
+#define CLOCK_PULSE(p, rdy) \
+ while ((inb(p) & rdy) == 0) { \
+ ; /* Do nothing */ \
+ }
+
+/*
+ * Read the serial EEPROM and returns 1 if successful and 0 if
+ * not successful.
+ */
+int read_seeprom (u_long offset,
+ u_short *buf,
+ int count,
+ u_short CS, /* chip select */
+ u_short CK, /* clock */
+ u_short DO, /* data out */
+ u_short DI, /* data in */
+ u_short RDY, /* ready */
+ u_short MS /* mode select */)
+{
+ int i = 0, k = 0;
+ int wait;
+ unsigned char temp;
+
+ /*
+ * Read the requested registers of the seeprom. The loop
+ * will range from 0 to count-1.
+ */
+ for (k = 0; k < count; k = k + 1) {
+ /* Send chip select for one clock cycle. */
+ outb(offset, MS | CK | CS);
+ CLOCK_PULSE(offset, RDY);
+
+ /*
+ * Now we're ready to send the read command followed by the
+ * address of the 16-bit register we want to read.
+ */
+ for (i = 0; i < seeprom_read.len; i = i + 1) {
+ if (seeprom_read.bits[i])
+ temp = MS | CS | DO;
+ else
+ temp = MS | CS;
+ outb(offset, temp);
+ CLOCK_PULSE(offset, RDY);
+ temp = temp ^ CK;
+ outb(offset, temp);
+ CLOCK_PULSE(offset, RDY);
+ }
+ /* Send the 6 bit address (MSB first, LSB last). */
+ for (i = 5; i >= 0; i = i - 1) {
+ /* k is the address, i is the bit */
+ if (k & (1 << i))
+ temp = MS | CS | DO;
+ else
+ temp = MS | CS;
+ outb(offset, temp);
+ CLOCK_PULSE(offset, RDY);
+ temp = temp ^ CK;
+ outb(offset, temp);
+ CLOCK_PULSE(offset, RDY);
+ }
+
+ /*
+ * Now read the 16 bit register. An initial 0 precedes the
+ * register contents which begins with bit 15 (MSB) and ends
+ * with bit 0 (LSB). The initial 0 will be shifted off the
+ * top of our word as we let the loop run from 0 to 16.
+ */
+ for (i = 0; i <= 16; i = i + 1) {
+ temp = MS | CS;
+ outb(offset, temp);
+ CLOCK_PULSE(offset, RDY);
+ temp = temp ^ CK;
+ if (inb(offset) & DI)
+ buf[k] = (buf[k] << 1) | 0x1;
+ else
+ buf[k] = (buf[k] << 1);
+ outb(offset, temp);
+ CLOCK_PULSE(offset, RDY);
+ }
+
+ /* Reset the chip select for the next command cycle. */
+ outb(offset, MS);
+ CLOCK_PULSE(offset, RDY);
+ outb(offset, MS | CK);
+ CLOCK_PULSE(offset, RDY);
+ outb(offset, MS);
+ CLOCK_PULSE(offset, RDY);
+ }
+
+#if 0
+ printf ("Serial EEPROM:");
+ for (k = 0; k < count; k = k + 1) {
+ if (((k % 8) == 0) && (k != 0))
+ {
+ printf ("\n ");
+ }
+ printf (" 0x%x", buf[k]);
+ }
+ printf ("\n");
+#endif
+ return (1);
+}
diff --git a/sys/i386/scsi/93cx6.h b/sys/i386/scsi/93cx6.h
new file mode 100644
index 0000000000000..dad5e3917148b
--- /dev/null
+++ b/sys/i386/scsi/93cx6.h
@@ -0,0 +1,52 @@
+/*
+ * Interface to the 93C46 serial EEPROM that is used to store BIOS
+ * settings for the aic7xxx based adaptec SCSI controllers. It can
+ * also be used for 93C26 and 93C06 serial EEPROMS.
+ *
+ * Copyright (c) 1994, 1995 Justin T. Gibbs.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Absolutely no warranty of function or purpose is made by the author
+ * Justin T. Gibbs.
+ * 4. Modifications may be freely made to this file if the above conditions
+ * are met.
+ *
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+/*
+ * This function will read count 16-bit words from the serial EEPROM and
+ * return their value in buf. The port address of the aic7xxx serial EEPROM
+ * control register is passed in as offset. The following parameters are
+ * also passed in:
+ *
+ * CS - Chip select
+ * CK - Clock
+ * DO - Data out
+ * DI - Data in
+ * RDY - SEEPROM ready
+ * MS - Memory port mode select
+ *
+ * A failed read attempt returns 0, and a successful read returns 1.
+ */
+int read_seeprom (u_long offset,
+ u_short *buf,
+ int count,
+ u_short CS,
+ u_short CK,
+ u_short DO,
+ u_short DI,
+ u_short RDY,
+ u_short MS);
diff --git a/sys/pccard/cis.h b/sys/pccard/cis.h
new file mode 100644
index 0000000000000..677b197a0a8c9
--- /dev/null
+++ b/sys/pccard/cis.h
@@ -0,0 +1,250 @@
+
+/*
+ * PCMCIA card structures and defines.
+ * These defines relate to the user level
+ * structures and card information, not
+ * driver/process communication.
+ *-------------------------------------------------------------------------
+ *
+ * Copyright (c) 1995 Andrew McRae. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Card Information Structure tuples definitions
+ * The structure of a tuple is basically:
+ *
+ * Tuple_code
+ * Tuple_data_length
+ * Tuple_data ...
+ *
+ * Tuples are contiguous in attribute memory, and
+ * are terminated with a 0xFF for the tuple code or
+ * the tuple length.
+ */
+#define CIS_NULL 0 /* Empty tuple */
+#define CIS_MEM_COMMON 0x01 /* Device descriptor, common memory */
+#define CIS_CHECKSUM 0x10 /* Checksum */
+#define CIS_LONGLINK_A 0x11 /* Link to Attribute memory */
+#define CIS_LONGLINK_C 0x12 /* Link to Common memory */
+#define CIS_LINKTARGET 0x13 /* Linked tuple must start with this. */
+#define CIS_NOLINK 0x14 /* Assume no common memory link tuple. */
+#define CIS_INFO_V1 0x15 /* Card info data, version 1 */
+#define CIS_ALTSTR 0x16 /* Alternate language string tuple. */
+#define CIS_MEM_ATTR 0x17 /* Device descriptor, Attribute memory */
+#define CIS_JEDEC_C 0x18 /* JEDEC descr for common memory */
+#define CIS_JEDEC_A 0x19 /* JEDEC descr for Attribute memory */
+#define CIS_CONF_MAP 0x1A /* Card Configuration map */
+#define CIS_CONFIG 0x1B /* Card Configuration entry */
+#define CIS_DEVICE_OC 0x1C /* Other conditions info - common memory */
+#define CIS_DEVICE_OA 0x1D /* Other conditions info - attribute memory */
+#define CIS_DEVICEGEO 0x1E /* Geometry info for common memory */
+#define CIS_DEVICEGEO_A 0x1F /* Geometry info for attribute memory */
+#define CIS_MANUF_ID 0x20 /* Card manufacturer's ID */
+#define CIS_FUNC_ID 0x21 /* Function of card */
+#define CIS_FUNC_EXT 0x22 /* Functional extension */
+/*
+ * Data recording format tuples.
+ */
+#define CIS_SW_INTERLV 0x23 /* Software interleave */
+#define CIS_VERS_2 0x40 /* Card info data, version 2 */
+#define CIS_FORMAT 0x41 /* Memory card format */
+#define CIS_GEOMETRY 0x42 /* Disk sector layout */
+#define CIS_BYTEORDER 0x43 /* Byte order of memory data */
+#define CIS_DATE 0x44 /* Format data/time */
+#define CIS_BATTERY 0x45 /* Battery replacement date */
+#define CIS_ORG 0x46 /* Organisation of data on card */
+#define CIS_END 0xFF /* Termination code */
+
+/*
+ * Internal tuple definitions.
+ *
+ * Device descriptor for memory (CIS_MEM_ATTR, CIS_MEM_COMMON)
+ *
+ * Byte 1:
+ * 0xF0 - Device type
+ * 0x08 - Write protect switch
+ * 0x07 - Speed index (7 = extended speed)
+ * Byte 2: Extended speed (bit 7 = another follows)
+ * Byte 3: (ignored if 0xFF)
+ * 0xF8 - Addressable units (0's numbered)
+ * 0x07 - Unit size
+ * The three byte sequence is repeated until byte 1 == 0xFF
+ */
+
+/*
+ * CIS_INFO_V1 - Version one card information.
+ *
+ * Byte 1: Major version number (should be 4)
+ * Byte 2: Minor version number (should be 1)
+ * Byte 3-x: Null terminated Manufacturer name
+ * Byte x-x: Null terminated product name
+ * Byte x-x: Null terminated additional info 1
+ * Byte x-x: Null terminated additional info 2
+ * Byte x: final byte must be 0xFF
+ */
+#define CIS_MAJOR_VERSION 4
+#define CIS_MINOR_VERSION 1
+
+/*
+ * CIS_CONF_MAP - Provides an address map for the card
+ * configuration register(s), and a max value
+ * identifying the last configuration tuple.
+ *
+ * Byte 1:
+ * 0x3C - Register mask size (0's numbered)
+ * 0x03 - Register address size (0's numbered)
+ * Byte 2:
+ * 0x3F - ID of last configuration.
+ * Byte 3-n: Card register address (size is determined by
+ * the value in byte 1).
+ * Byte x-x: Card register masks (size determined by the
+ * value in byte 1)
+ */
+
+/*
+ * CIS_CONFIG - Card configuration entry. Multiple tuples may
+ * exist of this type, each one describing a different
+ * memory/I-O map that can be used to address this card.
+ * The first one usually has extra config data about the
+ * card features. The final configuration tuple number
+ * is stored in the CIS_CONF_MAP tuple so that the complete
+ * list can be scanned.
+ *
+ * Byte 1:
+ * 0x3F - Configuration ID number.
+ * 0x40 - Indicates this is the default configuration
+ * 0x80 - Interface byte exists
+ * Byte 2: (exists only if bit 0x80 set in byte 1)
+ * 0x0F - Interface type value
+ * 0x10 - Battery voltage detect
+ * 0x20 - Write protect active
+ * 0x40 - RdyBsy active bit
+ * 0x80 - Wait signal required
+ * Byte 3: (features byte)
+ * 0x03 - Power sub-tuple(s) exists
+ * 0x04 - Timing sub-tuple exists
+ * 0x08 - I/O space sub-tuple exists
+ * 0x10 - IRQ sub-tuple exists
+ * 0x60 - Memory space sub-tuple(s) exists
+ * 0x80 - Miscellaneous sub-tuple exists
+ */
+#define CIS_FEAT_POWER(x) ((x) & 0x3)
+#define CIS_FEAT_TIMING 0x4
+#define CIS_FEAT_I_O 0x8
+#define CIS_FEAT_IRQ 0x10
+#define CIS_FEAT_MEMORY(x) (((x) >> 5) & 0x3)
+#define CIS_FEAT_MISC 0x80
+/*
+ * Depending on whether the "features" byte has the corresponding
+ * bit set, a number of sub-tuples follow. Some features have
+ * more than one sub-tuple, depending on the count within the
+ * features byte (e.g power feature bits allows up to 3 sub-tuples).
+ *
+ * Power structure sub-tuple:
+ * Byte 1: parameter exists - Each bit (starting from 0x01) indicates
+ * that a parameter block exists - up to 8 parameter blocks
+ * are therefore allowed).
+ * Byte 2:
+ * 0x7F - Parameter data
+ * 0x80 - More bytes follow (0 = last byte)
+ *
+ * Timing sub-tuple
+ * Byte 1:
+ * 0x03 - Wait scale
+ * 0x1C - Ready scale
+ * 0xE0 - Reserved scale
+ * Byte 2: extended wait scale if wait scale != 3
+ * Byte 3: extended ready scale if ready scale != 7
+ * Byte 4: extended reserved scale if reserved scale != 7
+ */
+#define CIS_WAIT_SCALE(x) ((x) & 0x3)
+#define CIS_READY_SCALE(x) (((x)>>2) & 0x7)
+#define CIS_RESERVED_SCALE(x) (((x)>>5) & 0x7)
+/*
+ * I/O mapping sub-tuple:
+ * Byte 1:
+ * 0x1F - I/O address lines
+ * 0x20 - 8 bit I/O
+ * 0x40 - 16 bit I/O
+ * 0x80 - I/O range??
+ * Byte 2:
+ * 0x0F - 0's numbered count of I/O block subtuples following.
+ * 0x30 - Size of I/O address value within subtuple. Values
+ * can be 1 (8 bits), 2 (16 bits) or 3 (32 bits).
+ * 0xC0 - Size of I/O port block size value within subtuple.
+ * I/O block sub-tuples, count from previous block:
+ * Byte 1-n: I/O start address
+ * Byte x-x: Size of I/O port block.
+ */
+#define CIS_IO_ADDR(x) ((x) & 0x1F)
+#define CIS_IO_8BIT 0x20
+#define CIS_IO_16BIT 0x40
+#define CIS_IO_RANGE 0x80
+#define CIS_IO_BLKS(x) ((x) & 0xF)
+#define CIS_IO_ADSZ(x) (((x)>>4) & 3)
+#define CIS_IO_BLKSZ(x) (((x)>>6) & 3)
+/*
+ * IRQ sub-tuple.
+ * Byte 1:
+ * 0x0F - Irq number or mask bits
+ * 0x10 - IRQ mask values exist
+ * 0x20 - Level triggered interrupts
+ * 0x40 - Pulse triggered requests
+ * 0x80 - Interrupt sharing.
+ * Byte 2-3: Interrupt req mask (if 0x10 of byte 1 set).
+ */
+#define CIS_IRQ_IRQN(x) ((x) & 0xF)
+#define CIS_IRQ_MASK 0x10
+#define CIS_IRQ_LEVEL 0x20
+#define CIS_IRQ_PULSE 0x40
+#define CIS_IRQ_SHARING 0x80
+/*
+ * Memory block subtuple. Depending on the features bits, the
+ * following subtuples are used:
+ * mem features == 1
+ * Byte 1-2: upper 16 bits of 24 bit memory length.
+ * mem features == 2
+ * Byte 1-2: upper 16 bits of 24 bit memory length.
+ * Byte 3-4: upper 16 bits of 24 bit memory address.
+ * mem_features == 3
+ * Byte 1:
+ * 0x07 - 0's numbered count of memory sub-tuples
+ * 0x18 - Memory length size (1's numbered)
+ * 0x60 - Memory address size (1's numbered)
+ * 0x80 - Host address value exists
+ * Memory sub-tuples follow:
+ * Byte 1-n: Memory length value (<< 8)
+ * Byte n-n: Memory card address value (<< 8)
+ * Byte n-n: Memory host address value (<< 8)
+ */
+#define CIS_FEAT_MEM_NONE 0 /* No memory config */
+#define CIS_FEAT_MEM_LEN 1 /* Just length */
+#define CIS_FEAT_MEM_ADDR 2 /* Card address & length */
+#define CIS_FEAT_MEM_WIN 3 /* Multiple windows */
+
+#define CIS_MEM_WINS(x) (((x) & 0x7)+1)
+#define CIS_MEM_LENSZ(x) (((x) >> 3) & 0x3)
+#define CIS_MEM_ADDRSZ(x) (((x) >> 5) & 0x3)
+#define CIS_MEM_HOST 0x80
diff --git a/sys/pccard/i82365.h b/sys/pccard/i82365.h
new file mode 100644
index 0000000000000..4c4d233b05764
--- /dev/null
+++ b/sys/pccard/i82365.h
@@ -0,0 +1,207 @@
+/*
+ * i82365.h - Definitions for Intel 82365 PCIC
+ * PCMCIA Card Interface Controller
+ *
+ * originally by Barry Jaspan; hacked over by Keith Moore
+ * hacked to unrecognisability by Andrew McRae (andrew@mega.com.au)
+ *
+ * Updated 3/3/95 to include Cirrus Logic stuff.
+ *-------------------------------------------------------------------------
+ *
+ * Copyright (c) 1995 Andrew McRae. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define PCIC_I82365 0 /* Intel chip */
+#define PCIC_IBM 1 /* IBM clone */
+#define PCIC_VLSI 2 /* VLSI chip */
+#define PCIC_PD672X 3 /* Cirrus logic 627x */
+#define PCIC_PD6710 4
+#define PCIC_CL6729 5
+#define PCIC_VG468 6
+/*
+ * Address of the controllers. Each controller can manage
+ * two PCMCIA slots. Up to 8 slots are supported in total.
+ * The PCIC controller is accessed via an index port and a
+ * data port. The index port has the 8 bit address of the
+ * register accessed via the data port. How I long for
+ * real memory mapped I/O!
+ * The top two bits of the index address are used to
+ * identify the port number, and the lower 6 bits
+ * select one of the 64 possible data registers.
+ */
+#define PCIC_INDEX_0 0x3E0 /* index reg, chips 0 and 1 */
+#define PCIC_DATA_0 0x3E1 /* data register, chips 0 and 1 */
+#define PCIC_INDEX_1 0x3E2 /* index reg, chips 2 and 3 */
+#define PCIC_DATA_1 0x3E3 /* data register, chips 2 and 3 */
+/*
+ * Register index addresses.
+ */
+#define PCIC_ID_REV 0x00 /* Identification and Revision */
+#define PCIC_STATUS 0x01 /* Interface Status */
+#define PCIC_POWER 0x02 /* Power and RESETDRV control */
+#define PCIC_INT_GEN 0x03 /* Interrupt and General Control */
+#define PCIC_STAT_CHG 0x04 /* Card Status Change */
+#define PCIC_STAT_INT 0x05 /* Card Status Change Interrupt Config */
+#define PCIC_ADDRWINE 0x06 /* Address Window Enable */
+#define PCIC_IOCTL 0x07 /* I/O Control */
+#define PCIC_IO0 0x08 /* I/O Address 0 */
+#define PCIC_IO1 0x0c /* I/O Address 1 */
+#define PCIC_MEMBASE 0x10 /* Base of memory window registers */
+#define PCIC_CDGC 0x16 /* Card Detect and General Control */
+#define PCIC_GLO_CTRL 0x1e /* Global Control Register */
+
+#define PCIC_TIME_SETUP0 0x3a
+#define PCIC_TIME_CMD0 0x3b
+#define PCIC_TIME_RECOV0 0x3c
+#define PCIC_TIME_SETUP1 0x3d
+#define PCIC_TIME_CMD1 0x3e
+#define PCIC_TIME_RECOV1 0x3f
+
+#define PCIC_SLOT_SIZE 0x40 /* Size of register set for one slot */
+
+/* Now register bits, ordered by reg # */
+
+/* For Identification and Revision (PCIC_ID_REV) */
+#define PCIC_INTEL0 0x82 /* Intel 82365SL Rev. 0; Both Memory and I/O */
+#define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */
+#define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */
+#define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */
+
+/* For Interface Status register (PCIC_STATUS) */
+#define PCIC_VPPV 0x80 /* Vpp_valid */
+#define PCIC_POW 0x40 /* PC Card power active */
+#define PCIC_READY 0x20 /* Ready/~Busy */
+#define PCIC_MWP 0x10 /* Memory Write Protect */
+#define PCIC_CD 0x0C /* Both card detect bits */
+#define PCIC_BVD 0x03 /* Both Battery Voltage Detect bits */
+
+/* For the Power and RESETDRV register (PCIC_POWER) */
+#define PCIC_OUTENA 0x80 /* Output Enable */
+#define PCIC_DISRST 0x40 /* Disable RESETDRV */
+#define PCIC_APSENA 0x20 /* Auto Pwer Switch Enable */
+#define PCIC_VCC 0x18 /* Vcc control bits */
+#define PCIC_VCC_5V 0x10 /* 5 volts */
+#define PCIC_VCC_3V 0x18 /* 3 volts */
+#define PCIC_VPP 0x0C /* Vpp control bits */
+#define PCIC_VPP_5V 0x01 /* 5 volts */
+#define PCIC_VPP_12V 0x02 /* 12 volts */
+
+/* For the Interrupt and General Control register (PCIC_INT_GEN) */
+#define PCIC_CARDTYPE 0x20 /* Card Type 0 = memory, 1 = I/O */
+#define PCIC_IOCARD 0x20
+#define PCIC_MEMCARD 0x00
+#define PCIC_CARDRESET 0x40 /* Card reset 0 = Reset, 1 = Normal */
+#define PCIC_INTR_ENA 0x10 /* Interrupt enable */
+
+/* For the Card Status Change register (PCIC_STAT_CHG) */
+#define PCIC_CDTCH 0x08 /* Card Detect Change */
+#define PCIC_RDYCH 0x04 /* Ready Change */
+#define PCIC_BATWRN 0x02 /* Battery Warning */
+#define PCIC_BATDED 0x01 /* Battery Dead */
+
+/*
+ * For the Address Window Enable Register (PCIC_ADDRWINE)
+ * The lower 6 bits contain enable bits for the memory
+ * windows (LSB = memory window 0).
+ */
+#define PCIC_MEMCS16 0x20 /* ~MEMCS16 Decode A23-A12 */
+#define PCIC_IO0_EN 0x40 /* I/O Window 0 Enable */
+#define PCIC_IO1_EN 0x80 /* I/O Window 1 Enable */
+
+/*
+ * For the I/O Control Register (PCIC_IOCTL)
+ * The lower nybble is the flags for I/O window 0
+ * The upper nybble is the flags for I/O window 1
+ */
+#define PCIC_IO_16BIT 0x01 /* I/O to this segment is 16 bit */
+#define PCIC_IO_CS16 0x02 /* I/O cs16 source is the card */
+#define PCIC_IO_0WS 0x04 /* zero wait states added on 8 bit cycles */
+#define PCIC_IO_WS 0x08 /* Wait states added for 16 bit cycles */
+
+/*
+ * The memory window registers contain the start and end
+ * physical host address that the PCIC maps to the card,
+ * and an offset calculated from the card memory address.
+ * All values are shifted down 12 bits, so allocation is
+ * done in 4Kb blocks. Only 12 bits of each value is
+ * stored, limiting the range to the ISA address size of
+ * 24 bits. The upper 4 bits of the most significant byte
+ * within the values are used for various flags.
+ *
+ * The layout is:
+ *
+ * base+0 : lower 8 bits of system memory start address
+ * base+1 : upper 4 bits of system memory start address + flags
+ * base+2 : lower 8 bits of system memory end address
+ * base+3 : upper 4 bits of system memory end address + flags
+ * base+4 : lower 8 bits of offset to card address
+ * base+5 : upper 4 bits of offset to card address + flags
+ *
+ * The following two bytes are reserved for other use.
+ */
+#define PCIC_MEMSIZE 8
+/*
+ * Flags for system memory start address upper byte
+ */
+#define PCIC_ZEROWS 0x40 /* Zero wait states */
+#define PCIC_DATA16 0x80 /* Data width is 16 bits */
+
+/*
+ * Flags for system memory end address upper byte
+ */
+#define PCIC_MW0 0x40 /* Wait state bit 0 */
+#define PCIC_MW1 0x80 /* Wait state bit 1 */
+
+/*
+ * Flags for card offset upper byte
+ */
+#define PCIC_REG 0x40 /* Attribute/Common select (why called Reg?) */
+#define PCIC_WP 0x80 /* Write-protect this window */
+
+/* For Card Detect and General Control register (PCIC_CDGC) */
+#define PCIC_16_DL_INH 0x01 /* 16-bit memory delay inhibit */
+#define PCIC_CNFG_RST_EN 0x02 /* configuration reset enable */
+#define PCIC_GPI_EN 0x04 /* GPI Enable */
+#define PCIC_GPI_TRANS 0x08 /* GPI Transition Control */
+#define PCIC_CDRES_EN 0x10 /* card detect resume enable */
+#define PCIC_SW_CD_INT 0x20 /* s/w card detect interrupt */
+
+/* For Global Control register (PCIC_GLO_CTRL) */
+#define PCIC_PWR_DOWN 0x01 /* power down */
+#define PCIC_LVL_MODE 0x02 /* level mode interrupt enable */
+#define PCIC_WB_CSCINT 0x04 /* explicit write-back csc intr */
+#define PCIC_IRQ0_LEVEL 0x08 /* irq 14 pulse mode enable */
+#define PCIC_IRQ1_LEVEL 0x10
+
+/*
+ * Mask of allowable interrupts.
+ * Ints are 3,4,5,7,9,10,11,12,14,15
+ */
+#define PCIC_INT_MASK_ALLOWED 0xDEB8
+
+#define PCIC_IO_WIN 2
+#define PCIC_MEM_WIN 5
+
+#define PCIC_MAX_SLOTS 8
diff --git a/sys/pccard/skel.c b/sys/pccard/skel.c
new file mode 100644
index 0000000000000..dd5b503bee582
--- /dev/null
+++ b/sys/pccard/skel.c
@@ -0,0 +1,189 @@
+/*
+ * Loadable kernel module skeleton driver
+ * 11 July 1995 Andrew McRae
+ *
+ *-------------------------------------------------------------------------
+ *
+ * Copyright (c) 1995 Andrew McRae. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/conf.h>
+#include <sys/mount.h>
+#include <sys/sysent.h>
+#include <sys/exec.h>
+#include <sys/lkm.h>
+#include <sys/errno.h>
+
+#include <pccard/card.h>
+#include <pccard/slot.h>
+
+/*
+ * This defines the lkm_misc module use by modload
+ * to define the module name.
+ */
+ MOD_MISC( "skel")
+
+
+static int skelintr(struct pccard_dev *); /* Interrupt handler */
+static void skelunload(struct pccard_dev *); /* Disable driver */
+static void skelsuspend(struct pccard_dev *); /* Suspend driver */
+static int skelinit(struct pccard_dev *, int); /* init device */
+
+static struct pccard_drv skel_info =
+ {
+ "skel",
+ skelintr,
+ skelunload,
+ skelsuspend,
+ skelinit,
+ };
+static int opened; /* Rather minimal device state... */
+
+/*
+ * Module handler that processes loads and unloads.
+ * Once the module is loaded, the add driver routine is called
+ * to register the driver.
+ * If an unload is requested the remove driver routine is
+ * called to deregister the driver before unloading.
+ */
+static int
+skel_handle( lkmtp, cmd)
+struct lkm_table *lkmtp;
+int cmd;
+{
+ int i;
+ struct lkm_misc *args = lkmtp->private.lkm_misc;
+ int err = 0; /* default = success*/
+
+ switch( cmd) {
+ case LKM_E_LOAD:
+
+ /*
+ * Don't load twice! (lkmexists() is exported by kern_lkm.c)
+ */
+ if( lkmexists( lkmtp))
+ return( EEXIST);
+/*
+ * Now register the driver
+ */
+ pccard_add_driver(&skel_info);
+ break; /* Success*/
+/*
+ * Attempt to deregister the driver.
+ */
+ case LKM_E_UNLOAD:
+ pccard_remove_driver(&skel_info);
+ break; /* Success*/
+
+ default: /* we only understand load/unload*/
+ err = EINVAL;
+ break;
+ }
+
+ return( err);
+}
+
+
+/*
+ * External entry point; should generally match name of .o file. The
+ * arguments are always the same for all loaded modules. The "load",
+ * "unload", and "stat" functions in "DISPATCH" will be called under
+ * their respective circumstances unless their value is "nosys". If
+ * called, they are called with the same arguments (cmd is included to
+ * allow the use of a single function, ver is included for version
+ * matching between modules and the kernel loader for the modules).
+ *
+ * Since we expect to link in the kernel and add external symbols to
+ * the kernel symbol name space in a future version, generally all
+ * functions used in the implementation of a particular module should
+ * be static unless they are expected to be seen in other modules or
+ * to resolve unresolved symbols alread existing in the kernel (the
+ * second case is not likely to ever occur).
+ *
+ * The entry point should return 0 unless it is refusing load (in which
+ * case it should return an errno from errno.h).
+ */
+int
+lkm_skel(lkmtp, cmd, ver)
+struct lkm_table *lkmtp;
+int cmd;
+int ver;
+{
+ DISPATCH(lkmtp,cmd,ver,skel_handle,skel_handle,nosys)
+}
+/*
+ * Skeleton driver entry points for PCCARD configuration.
+ */
+/*
+ * The device entry is being removed. Shut it down,
+ * and turn off interrupts etc. Not called unless
+ * the device was successfully installed.
+ */
+static void
+skelunload(struct pccard_dev *dp)
+{
+ printf("skel%d: unload\n", dp->unit);
+ opened &= ~(1 << dp->unit);
+}
+/*
+ * Called when a power down is wanted. Shuts down the
+ * device and configures the device as unavailable (but
+ * still loaded...). A resume is done by calling
+ * skelinit with first=0.
+ */
+static void
+skelsuspend(struct pccard_dev *dp)
+{
+ printf("skel%d: suspending\n", dp->unit);
+}
+/*
+ * Initialize the device.
+ * if first is set, then initially check for
+ * the device's existence before initialising it.
+ * Once initialised, the device table may be set up.
+ */
+static int
+skelinit(struct pccard_dev *dp, int first)
+{
+ if (first && ((1 << dp->unit)&opened))
+ return(EBUSY);
+ if (first)
+ opened |= 1 << dp->unit;
+ printf("skel%d: init, first = %d\n", dp->unit, first);
+ printf("iomem = 0x%x, iobase = 0x%x\n", dp->memory, dp->ioaddr);
+ return(0);
+}
+/*
+ * Interrupt handler.
+ * Returns true if the interrupt is for us.
+ */
+static int
+skelintr(struct pccard_dev *dp)
+{
+ return(0);
+}
diff --git a/usr.bin/at/LEGAL b/usr.bin/at/LEGAL
new file mode 100644
index 0000000000000..92b1b4983110c
--- /dev/null
+++ b/usr.bin/at/LEGAL
@@ -0,0 +1,29 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+
+Sorry for the long wait, but there still were a few things to
+be ironed out in at, which I've finally done :-)
+
+The FreeBSD team does have my permission to use at, version 2.9,
+under the BSD license.
+
+You'll find it on sunsite.unc.edu's Incoming, hopefully; the
+md5 checksum is
+
+3ba2ca3c0e87e1a04feae2c6c1376b0d at-2.9.tgz
+
+Best regards
+ Thomas
+- --
+Thomas Koenig, Thomas.Koenig@ciw.uni-karlsruhe.de, ig25@dkauni2.bitnet.
+The joy of engineering is to find a straight line on a double
+logarithmic diagram.
+
+-----BEGIN PGP SIGNATURE-----
+Version: 2.6.2i
+
+iQCVAwUBMCjVrPBu+cbJcKCVAQFNiQP/dpWP57s/E8plVGUD3zfgOXDmKUvg8U7a
+VwRzJrIMuSgnSJs0wkpvcomc3NLicipfX7hhWLh/xatPM2YbF7O5HZoNdvWvexD2
+1Y67zJ+0HFb1mPnSBOrS5RFiQAe3KqmGec6E14Rih/qNoFQZBVRFXZ4xxuwP+0Rs
+e2U+TVTUz6A=
+=TvyW
+-----END PGP SIGNATURE-----
diff --git a/usr.bin/chpass/pw_yp.c b/usr.bin/chpass/pw_yp.c
new file mode 100644
index 0000000000000..6fd87f5470794
--- /dev/null
+++ b/usr.bin/chpass/pw_yp.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 1995
+ * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * NIS interface routines for chpass
+ *
+ * Written by Bill Paul <wpaul@ctr.columbia.edu>
+ * Center for Telecommunications Research
+ * Columbia University, New York City
+ *
+ * $Id$
+ */
+
+#ifdef YP
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <time.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+#include <err.h>
+#include <unistd.h>
+#include <db.h>
+#include <fcntl.h>
+#include <utmp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <limits.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yppasswd.h>
+#include <pw_util.h>
+#include "pw_yp.h"
+
+#define PERM_SECURE (S_IRUSR|S_IWUSR)
+HASHINFO openinfo = {
+ 4096, /* bsize */
+ 32, /* ffactor */
+ 256, /* nelem */
+ 2048 * 1024, /* cachesize */
+ NULL, /* hash */
+ 0, /* lorder */
+};
+
+int _use_yp = 0;
+
+/*
+ * Check if the user we're working with is local or in NIS.
+ */
+int use_yp (user)
+char *user;
+{
+ int yp_enabled = 0, user_not_local = 0, exists = 0;
+ DB *dbp;
+ DBT key,data;
+ char bf[UT_NAMESIZE + 2];
+
+ if ((dbp = dbopen(_PATH_MP_DB, O_RDONLY, PERM_SECURE,
+ DB_HASH, &openinfo)) == NULL)
+ errx(1, "error opening database: %s.", _PATH_MP_DB);
+ bf[0] = _PW_KEYYPENABLED;
+ key.data = (u_char *)bf;
+ key.size = 1;
+ if (!(dbp->get)(dbp,&key,&data,0))
+ yp_enabled = 1;
+
+ bf[0] = _PW_KEYBYNAME;
+ bcopy((char *)user, bf + 1, MIN(strlen(user), UT_NAMESIZE));
+ key.data = (u_char *)bf;
+ key.size = strlen(user) + 1;
+ if ((dbp->get)(dbp,&key,&data,0))
+ user_not_local = 1;
+
+ (dbp->close)(dbp);
+
+ if (getpwnam(user) != NULL)
+ exists = 1;
+
+ if (yp_enabled && user_not_local && exists)
+ return(1);
+ else
+ return(0);
+}
+
+/*
+ * Find the name of the NIS master server for this domain
+ * and make sure it's running yppasswdd.
+ */
+static char *get_yp_master(void)
+{
+ char *domain, *mastername;
+ int rval;
+
+ /* Get default NIS domain. */
+
+ if ((rval = yp_get_default_domain(&domain))) {
+ warnx("can't get local NIS domain name: %s",yperr_string(rval));
+ pw_error(NULL, 0, 1);
+ }
+
+ /* Get master server of passwd map. */
+
+ if ((rval = yp_master(domain, "passwd.byname", &mastername))) {
+ warnx("can't get master NIS server: %s", yperr_string(rval));
+ pw_error(NULL, 0, 1);
+ }
+
+ /* Check if yppasswdd is out there. */
+
+ if ((rval = getrpcport(mastername, YPPASSWDPROG, YPPASSWDPROC_UPDATE,
+ IPPROTO_UDP)) == 0) {
+ warnx("yppasswdd not running on NIS master server");
+ pw_error(NULL, 0, 1);
+ }
+
+ /*
+ * Make sure it's on a reserved port.
+ * XXX Might break with yppasswdd servers running on Solaris 2.x.
+ */
+
+ if (rval >= IPPORT_RESERVED) {
+ warnx("yppasswdd server not running on reserved port");
+ pw_error(NULL, 0, 1);
+ }
+
+ /* Everything checks out: return the name of the server. */
+
+ return (mastername);
+}
+/*
+ * Ask the user for his NIS password and submit the new information
+ * to yppasswdd. Note that yppasswdd requires password authentication
+ * and only allows changes to existing records rather than the addition
+ * of new records. (To do actual updates we would need something like
+ * secure RPC and ypupdated, which FreeBSD doesn't have yet.) This means
+ * that the superuser cannot use chpass(1) to add new users records to
+ * the NIS password database.
+ */
+void yp_submit(pw)
+struct passwd *pw;
+{
+ struct yppasswd yppasswd;
+ CLIENT *clnt;
+ char *master, *password, *encpass;
+ int rval, status = 0;
+ struct timeval tv;
+
+ /* Populate the yppasswd structure that gets handed to yppasswdd. */
+ /*
+ * XXX This is done first to work around what looks like a very
+ * strange memory corruption bug: the text fields pointed to
+ * by the members of the 'pw' structure appear to be clobbered
+ * after get_yp_master() returns (in particular, it happens
+ * during getrpcport()). I don't know exactly where the problem
+ * lies: I traced it all the way to gethostbyname(), then gave
+ * up.
+ */
+ yppasswd.newpw.pw_passwd = strdup(pw->pw_passwd);
+ yppasswd.newpw.pw_name = strdup(pw->pw_name);
+ yppasswd.newpw.pw_uid = pw->pw_uid;
+ yppasswd.newpw.pw_gid = pw->pw_gid;
+ yppasswd.newpw.pw_gecos = strdup(pw->pw_gecos);
+ yppasswd.newpw.pw_dir = strdup(pw->pw_dir);
+ yppasswd.newpw.pw_shell = strdup(pw->pw_shell);
+
+ /* Get NIS master server name */
+
+ master = get_yp_master();
+
+ /* Get the user's password for authentication purposes. */
+
+ printf ("Changing NIS information for %s on %s\n",
+ yppasswd.newpw.pw_name, master);
+ encpass = (getpwnam(yppasswd.newpw.pw_name))->pw_passwd;
+ password = getpass("Please enter password: ");
+ if (strncmp(crypt(password, encpass), encpass, strlen(encpass))) {
+ warnx("Password incorrect.");
+ pw_error(NULL, 0, 1);
+ }
+
+ yppasswd.oldpass = password; /* XXX */
+
+ /* Create a handle to yppasswdd. */
+
+ clnt = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
+ clnt->cl_auth = authunix_create_default();
+
+ /* Set a timeout and make the RPC call. */
+
+ tv.tv_sec = 20;
+ tv.tv_usec = 0;
+ rval = clnt_call(clnt, YPPASSWDPROC_UPDATE, xdr_yppasswd,
+ (char *)&yppasswd, xdr_int, (char *)&status, &tv);
+
+ /* Call failed: signal the error. */
+
+ if (rval) {
+ warnx("NIS update failed: %s", clnt_sperrno(rval));
+ pw_error(NULL, 0, 1);
+ }
+
+ /* Success. */
+
+ auth_destroy(clnt->cl_auth);
+ clnt_destroy(clnt);
+ warnx("NIS information changed on host %s", master);
+
+ return;
+}
+#endif /* YP */
diff --git a/usr.bin/chpass/pw_yp.h b/usr.bin/chpass/pw_yp.h
new file mode 100644
index 0000000000000..94c7a74090d2b
--- /dev/null
+++ b/usr.bin/chpass/pw_yp.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1995
+ * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * NIS interface routines for chpass
+ *
+ * Written by Bill Paul <wpaul@ctr.columbia.edu>
+ * Center for Telecommunications Research
+ * Columbia University, New York City
+ *
+ * $Id$
+ */
+
+#ifdef YP
+extern int _use_yp;
+void yp_submit __P(( struct passwd * ));
+int use_yp __P(( char * ));
+#endif /* YP */
diff --git a/usr.bin/ee/Makefile b/usr.bin/ee/Makefile
new file mode 100644
index 0000000000000..dbe6f4e1613f0
--- /dev/null
+++ b/usr.bin/ee/Makefile
@@ -0,0 +1,18 @@
+CFLAGS+= -DCAP -DHAS_NCURSES -DHAS_UNISTD -DHAS_STDARG -DHAS_STDLIB \
+ -DHAS_CTYPE -DHAS_SYS_IOCTL -DHAS_SYS_WAIT -DSLCT_HDR
+
+PROG= ee
+SRCS= ee.c
+LINKS= ${BINDIR}/ee ${BINDIR}/ree
+DPADD= ${LIBNCURSES} ${LIBMYTINFO}
+LDADD= -lncurses -lmytinfo
+
+LANGS= en_US.ISO_8859-1
+
+afterinstall:
+ @for i in ${LANGS}; do \
+ gencat -new ${DESTDIR}/usr/share/nls/$$i/ee.cat ${.CURDIR}/nls/$$i/ee.msg; \
+ chmod 444 ${.CURDIR}/nls/$$i/ee.msg; \
+ done
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/ee/README b/usr.bin/ee/README
new file mode 100644
index 0000000000000..e15070077a981
--- /dev/null
+++ b/usr.bin/ee/README
@@ -0,0 +1,116 @@
+ THIS MATERIAL IS PROVIDED "AS IS". THERE ARE NO WARRANTIES OF
+ ANY KIND WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE. Neither Hewlett-Packard nor
+ Hugh Mahon shall be liable for errors contained herein, nor for
+ incidental or consequential damages in connection with the
+ furnishing, performance or use of this material. Neither
+ Hewlett-Packard nor Hugh Mahon assumes any responsibility for
+ the use or reliability of this software or documentation. This
+ software and documentation is totally UNSUPPORTED. There is no
+ support contract available. Hewlett-Packard has done NO
+ Quality Assurance on ANY of the program or documentation. You
+ may find the quality of the materials inferior to supported
+ materials.
+
+ This software may be distributed under the terms of Larry Wall's
+ Artistic license, a copy of which is included in this distribution.
+ (see doc/Artistic).
+
+ This notice must be included with this software and any
+ derivatives.
+
+ Any modifications to this software by anyone but the original author
+ must be so noted.
+
+
+The editor 'ee' (easy editor) is intended to be a simple, easy to use
+terminal-based screen oriented editor that requires no instruction to
+use. Its primary use would be for people who are new to computers, or who
+use computers only for things like e-mail.
+
+ee's simplified interface is highlighted by the use of pop-up menus which
+make it possible for users to carry out tasks without the need to
+remember commands. An information window at the top of the screen shows
+the user the operations available with control-keys.
+
+ee allows users to use full eight-bit characters. If the host system has
+the capabilities, ee can use message catalogs, which would allow users to
+translate the message catalog into other languages which use eight-bit
+characters. See the file ee.i18n.guide for more details.
+
+ee relies on the virtual memory abilities of the platform it is running on
+and does not have its own memory management capabilities.
+
+I am releasing ee because I hate to see new users and non-computer types
+get frustrated by vi, and would like to see more intuitive interfaces for
+basic tools (both character-based and graphical) become more pervasive.
+Terminal capabilities and communication speeds have evolved considerably
+since the time in which vi's interface was created, allowing much more
+intuitive interfaces to be used. Since character-based I/O won't be
+completely replaced by graphical user interfaces for at least a few more
+years, I'd like to do what I can to make using computers with less
+glamorous interfaces as easy to use as possible. If terminal interfaces
+are still used in ten years, I hope neophytes won't still be stuck with
+only vi.
+
+For a text editor to be easy to use requires a certain set of abilities. In
+order for ee to work, a terminal must have the ability to position the cursor
+on the screen, and should have arrow keys that send unique sequences
+(multiple characters, the first character is an "escape", octal code
+'\033'). All of this information needs to be in a database called "terminfo"
+(System V implementations) or "termcap" (usually used for BSD systems). In
+case the arrow keys do not transmit unique sequences, motion operations are
+mapped to control keys as well, but this at least partially defeats the
+purpose. The curses package is used to handle the I/O which deals with the
+terminal's capabilities.
+
+While ee is based on curses, I have included here the source code to
+new_curse, a subset of curses developed for use with ee. 'curses' often
+will have a defect that reduces the usefulness of the editor relying upon
+it. This is unused by the FreeBSD version of ee (the existing ncurses
+library works just fine) but is included in the doc subdirectory for
+reference purposes should anyone wish to port ee to a platform for
+which the existing curses libraries are insufficient.
+
+The files doc/new_curse.[ch] contain a subset of the 'curses' library
+used by applications to handle screen output. Unfortunately, curses
+varies from system to system, so I developed new_curse to provide
+consistent behavior across systems. It works on both SystemV and BSD
+systems, and while it can sometimes be slower than other curses packages,
+it will get the information on the screen painted correctly more often
+than vendor supplied curses. Again, FreeBSD does not have this problem
+but you may find it useful on other platforms.
+
+If you experience problems with data being displayed improperly, check
+your terminal configuration, especially if you're using a terminal
+emulator, and make sure that you are using the right terminfo entry
+before rummaging through code. Terminfo entries often contain
+inaccuracies, or incomplete information, or may not totally match the
+terminal or emulator the terminal information is being used with.
+Complaints that ee isn't working quite right often end up being something
+else (like the terminal emulator being used).
+
+Both ee and new_curse were developed using K&R C (also known as "classic
+C"), but it can also be compiled with ANSI C. You should be able to
+build ee by simply typing "make".
+
+ee is the result of several conflicting design goals. While I know that it
+solves the problems of some users, I also have no doubt that some will decry
+its lack of more features. I will settle for knowing that ee does fulfill
+the needs of a minority (but still large number) of users. The goals of ee
+are:
+
+ 1. To be so easy to use as to require no instruction.
+ 2. To be easy to compile and, if necessary, port to new platforms
+ by people with relatively little knowledge of C and UNIX.
+ 3. To have a minimum number of files to be dealt with, for compile
+ and installation.
+ 4. To have enough functionality to be useful to a large number of
+ people.
+
+Hugh Mahon |___|
+h_mahon@fc.hp.com | |
+ |\ /|
+ | \/ |
+
diff --git a/usr.bin/ee/doc/Artistic b/usr.bin/ee/doc/Artistic
new file mode 100644
index 0000000000000..fbf798977589c
--- /dev/null
+++ b/usr.bin/ee/doc/Artistic
@@ -0,0 +1,117 @@
+
+
+
+
+ The "Artistic License"
+
+ Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain or from the Copyright Holder. A Package
+modified in such a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as uunet.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) accompany any non-standard executables with their corresponding
+ Standard Version executables, giving the non-standard executables
+ non-standard names, and clearly documenting the differences in manual
+ pages (or equivalent), together with instructions on where to get
+ the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this Package.
+You may not charge a fee for this Package itself. However,
+you may distribute this Package in aggregate with other (possibly
+commercial) programs as part of a larger (possibly commercial) software
+distribution provided that you do not advertise this Package as a
+product of your own.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whomever generated
+them, and may be sold commercially, and may be aggregated with this
+Package.
+
+7. C subroutines supplied by you and linked into this Package in order
+to emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ The End
diff --git a/usr.bin/ee/doc/ee.i18n.guide b/usr.bin/ee/doc/ee.i18n.guide
new file mode 100644
index 0000000000000..0850c2e7400d0
--- /dev/null
+++ b/usr.bin/ee/doc/ee.i18n.guide
@@ -0,0 +1,141 @@
+Easy Editor ("ee") provides the ability to translate the messages displayed to
+the user and the commands entered. This is done via message catalogs,
+following X/Open standards. ee only supports eight bit characters.
+
+(The name ee.i18n.guide is for "ee internationalization guide". The i18n
+abbreviation is used because there are 18 characters between the first
+letter ("i") and last ("n") of "internationalization".)
+
+All of the messages, warnings, information, and commands, are contained in the
+message catalog. Each numbered entry represents an individual string used by
+ee. Some strings contain formatting information for formatted print
+statements, which are of the form "%s", or "%d", these must be preserved in
+the translation, or the correct information will not be displayed. For those
+strings containing multiple formatting codes, the order of each item must be
+preserved as well.
+
+Message content
+1 title for modes, or settings menu
+2 - 8 entries for modes menu, each line should be the same length
+ (padded with spaces)
+9 - 34 other menu titles and entries
+35 - 56 help screen
+57 - 61 actions assigned to control keys
+62 - 66 commands information
+67 message displayed when info window turned off
+68 indication that no file name was entered when invoking ee
+69 prompt for decimal value of character to be entered
+70 message displaying the print command being invoked
+71 prompt for command
+72 prompt for name of file to be written
+73 prompt for name of file to be read
+74 string used to display the decimal value of the character
+ the cursor is on
+75 string displaying an unrecognized command
+76 string indicating that the command entered is not a unique
+ substring of a valid command
+77 string indicating the current line number
+78 string for displaying the length of the line
+79 string for displaying the name of the file
+80 - 83 strings showing how to invoke ee, and its options
+84 message indicating that the file entered is a directory, not a
+ text file
+85 message informing that the entered file does not yet exist
+86 message informing that the file can't be opened (because of
+ permission problems)
+87 message after file has been read with the file name and number
+ of lines read
+88 message indicating that the file has been read
+89 message indicating that the file is being read
+90 message indicating that permissions only allow the file to be
+ read, not written
+91 message after file has been read with the file name and number
+ of lines read
+92 prompt for name of file to be saved (used when no name was
+ entered for a file to edit)
+93 message indicating that the file was not written, since no
+ name was entered at the prompt
+94 prompt asking user if changes should not be saved ("yes_char"
+ will be expected for affirmative response)
+95 "yes" character, single character expected to confirm action
+ (can be upper or lower case, will be converted to upper-case
+ during test)
+96 prompt
+97 error message
+98 message indicating that the named file is being written
+99 message indicating the name of the file written, the number of
+ lines, and the number of characters (order of items must be
+ maintained)
+100 search in progress message
+101 message that the string was not found
+102 prompt for search
+103 message that string could not be executed
+104 self-explanatory
+105 message for menus, indicating that the Escape character will
+ allow the user to exit the menu
+106 error message indicating the menu won't fit on the screen
+107 self-explanatory
+108 prompt for shell command
+109 message displayed while formatting a paragraph
+110 string which places message for spell checking at top of
+ buffer (the portions 'list of unrecognized words' and
+ '-=-=-=-=-=-' may be replaced, but the rest must remain the
+ same)
+111 message informing that spell checking is in progress
+112 prompt for right margin
+113 error informing user that operation is not permitted in ree
+114 string indicating mode is turned 'on' in modes menu
+115 string indicating mode is turned 'off' in modes menu
+116 - 131 strings used for commands (some also used for initialization)
+132 - 144 strings used for initialization
+145 entry for settings menu for emacs key bindings settings
+146 - 153 help screen entries for emacs key bindings info
+154 - 158 info window entries for emacs key bindings info
+159 string for turning on emacs key bindings in the init file
+160 string for turning off emacs key bindings in the init file
+
+Care should be taken when translating commands and initialization keywords
+because the algorithm used for detecting uniqueness of entered commands
+will not be able to distinguish words that are not unique before the end
+of the shorter word, for example, it would not be able to distinguish the
+command 'abcd' from 'abcde'.
+
+After translating the messages, use the 'gencat' command to create the compiled
+catalog used when running the software. The standard syntax would be:
+
+ gencat ee.cat ee.msg
+
+Where ee.msg is the file containing the translations, and ee.cat is the
+compiled catalog. If the file ee.cat does not exist, it will be created.
+Check the documentation for your system for proper syntax.
+
+Message catalog placement varies from system to system. A common location
+for message catalogs is in /usr/lib/nls. In this directory are
+directories with the names of other languages. The default language is
+'C'. There is also an environment variable, named NLSPATH used to
+determine where message catalogs can be found. This variable is similar
+to the PATH variable used for commands, but with some differences. The
+NLSPATH variable must have the ability to handle different names for
+languages and the catalog files, so it has field descriptors for these. A
+typical setting for NLSPATH could be:
+
+ NLSPATH=/usr/lib/nls/%L/%N.cat:/usr/local/lib/nls/%L/%N.cat
+
+Where "%L" is the field descriptor for the language (obtained from the
+LANG environment variable) and "%N" is the name of the file (with the
+".cat" appended by the path variable, it is not passed from the requesting
+program). The colon (:) is used to separate paths, so in the above
+example there are two paths possible for message catalogs. You may wish
+to maintain catalogs for applications that are not supported by your
+system vendor in a location unique for you, and this is facilitated by the
+NLSPATH variable. Remember to set and export both the LANG and NLSPATH
+variables for each user that expects to use localization either in a
+system-wide profile or in each user's profile. See your system
+documentation for more information.
+
+The message catalog supplied with ee also uses the '$quote' directive to
+specify a quote around strings to ensure proper padding. This directive
+may not be supported on all systems, and lead to quotes being included in
+the string used in ee, which will cause incorrect behavior. If the
+'$quote' directive is not supported by your system's gencat command, edit
+the msg file to remove the leading and trailing quotation marks.
diff --git a/usr.bin/ee/doc/new_curse.c b/usr.bin/ee/doc/new_curse.c
new file mode 100644
index 0000000000000..0e6cd54831cfe
--- /dev/null
+++ b/usr.bin/ee/doc/new_curse.c
@@ -0,0 +1,3574 @@
+/*
+ | new_curse.c
+ |
+ | A subset of curses developed for use with ae.
+ |
+ | written by Hugh Mahon
+ |
+ | THIS MATERIAL IS PROVIDED "AS IS". THERE ARE
+ | NO WARRANTIES OF ANY KIND WITH REGARD TO THIS
+ | MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE
+ | IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ | FITNESS FOR A PARTICULAR PURPOSE. Neither
+ | Hewlett-Packard nor Hugh Mahon shall be liable
+ | for errors contained herein, nor for
+ | incidental or consequential damages in
+ | connection with the furnishing, performance or
+ | use of this material. Neither Hewlett-Packard
+ | nor Hugh Mahon assumes any responsibility for
+ | the use or reliability of this software or
+ | documentation. This software and
+ | documentation is totally UNSUPPORTED. There
+ | is no support contract available. Hewlett-
+ | Packard has done NO Quality Assurance on ANY
+ | of the program or documentation. You may find
+ | the quality of the materials inferior to
+ | supported materials.
+ |
+ | This software is not a product of Hewlett-Packard, Co., or any
+ | other company. No support is implied or offered with this software.
+ | You've got the source, and you're on your own.
+ |
+ | This software may be distributed under the terms of Larry Wall's
+ | Artistic license, a copy of which is included in this distribution.
+ |
+ | This notice must be included with this software and any derivatives.
+ |
+ | Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995 Hugh Mahon
+ | All are rights reserved.
+ |
+ | $Header: /home/hugh/sources/old_ae/RCS/new_curse.c,v 1.37 1995/08/28 23:49:26 hugh Exp $
+ |
+ */
+
+char *copyright_message[] = { "Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995 Hugh Mahon",
+ "All rights are reserved."};
+
+char * new_curse_name= "@(#) new_curse.c $Revision: 1.37 $";
+
+#include "new_curse.h"
+#include <signal.h>
+#include <fcntl.h>
+
+#ifdef SYS5
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#ifdef BSD_SELECT
+#include <sys/types.h>
+#include <sys/time.h>
+
+#ifdef SLCT_HDR
+#include <sys/select.h> /* on AIX */
+#endif /* SLCT_HDR */
+
+#endif /* BSD_SELECT */
+
+#ifdef HAS_STDLIB
+#include <stdlib.h>
+#endif
+
+#if defined(__STDC__)
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef HAS_UNISTD
+#include <unistd.h>
+#endif
+
+#ifdef HAS_SYS_IOCTL
+#include <sys/ioctl.h>
+#endif
+
+
+WINDOW *curscr;
+static WINDOW *virtual_scr;
+WINDOW *stdscr;
+WINDOW *last_window_refreshed;
+
+#ifdef TIOCGWINSZ
+ struct winsize ws;
+#endif
+
+#define min(a, b) (a < b ? a : b)
+
+#ifndef CAP
+#define String_Out(table, stack, place) Info_Out(table, stack, place)
+#else
+#define String_Out(table, stack, place) Cap_Out(table, stack, place)
+#endif
+
+#define bw__ 0 /* booleans */
+#define am__ 1
+#define xb__ 2
+#define xs__ 3 /* hp glitch (standout not erased by overwrite) */
+#define xn__ 4
+#define eo__ 5
+#define gn__ 6 /* generic type terminal */
+#define hc__ 7 /* hardcopy terminal */
+#define km__ 8
+#define hs__ 9
+#define in__ 10
+#define da__ 11
+#define db__ 12
+#define mi__ 13 /* safe to move during insert mode */
+#define ms__ 14 /* safe to move during standout mode */
+#define os__ 15
+#define es__ 16
+#define xt__ 17
+#define hz__ 18 /* hazeltine glitch */
+#define ul__ 19
+#define xo__ 20
+#define chts__ 21
+#define nxon__ 22
+#define nrrmc__ 23
+#define npc__ 24
+#define mc5i__ 25
+
+#define co__ 0 /* number of columns */ /* numbers */
+#define it__ 1 /* spaces per tab */
+#define li__ 2 /* number of lines */
+#define lm__ 3
+#define sg__ 4 /* magic cookie glitch */
+#define pb__ 5
+#define vt__ 6
+#define ws__ 7
+
+#define cols__ 0
+#define lines__ 2
+#define xmc__ 4
+#define vt__ 6
+#define wsl__ 7
+#define nlab__ 8
+#define lh__ 9
+#define lw__ 10
+
+#define bt__ 0 /* back tab */ /* strings */
+#define bl__ 1 /* bell */
+#define cr__ 2 /* carriage return */
+#define cs__ 3 /* change scroll region */
+#define ct__ 4 /* clear all tab stops */
+#define cl__ 5 /* clear screen and home cursor */
+#define ce__ 6 /* clear to end of line */
+#define cd__ 7 /* clear to end of display */
+#define ch__ 8 /* set cursor column */
+#define CC__ 9 /* term, settable cmd char in */
+#define cm__ 10 /* screen rel cursor motion, row, column */
+#define do__ 11 /* down one line */
+#define ho__ 12 /* home cursor */
+#define vi__ 13 /* make cursor invisible */
+#define le__ 14 /* move cursor left one space */
+#define CM__ 15 /* memory rel cursor addressing */
+#define ve__ 16 /* make cursor appear normal */
+#define nd__ 17 /* non-destructive space (cursor right) */
+#define ll__ 18 /* last line, first col */
+#define up__ 19 /* cursor up */
+#define vs__ 20
+#define dc__ 21 /* delete character */
+#define dl__ 22 /* delete line */
+#define ds__ 23
+#define hd__ 24
+#define as__ 25
+#define mb__ 26
+#define md__ 27 /* turn on bold */
+#define ti__ 28
+#define dm__ 29 /* turn on delete mode */
+#define mh__ 30 /* half bright mode */
+#define im__ 31 /* insert mode */
+#define mk__ 32
+#define mp__ 33
+#define mr__ 34
+#define so__ 35 /* enter standout mode */
+#define us__ 36
+#define ec__ 37
+#define ae__ 38
+#define me__ 39
+#define te__ 40
+#define ed__ 41
+#define ei__ 42 /* exit insert mode */
+#define se__ 43 /* exit standout mode */
+#define ue__ 44
+#define vb__ 45
+#define ff__ 46
+#define fs__ 47
+#define i1__ 48
+#define i2__ 49
+#define i3__ 50
+#define if__ 51
+#define ic__ 52
+#define al__ 53
+#define ip__ 54
+#define kb__ 55 /* backspace key */
+#define ka__ 56
+#define kC__ 57
+#define kt__ 58
+#define kD__ 59
+#define kL__ 60
+#define kd__ 61
+#define kM__ 62
+#define kE__ 63
+#define kS__ 64
+#define k0__ 65
+#define k1__ 66
+#define kf10__ 67
+#define k2__ 68
+#define k3__ 69
+#define k4__ 70
+#define k5__ 71
+#define k6__ 72
+#define k7__ 73
+#define k8__ 74
+#define k9__ 75
+#define kh__ 76
+#define kI__ 77
+#define kA__ 78
+#define kl__ 79
+#define kH__ 80
+#define kN__ 81
+#define kP__ 82
+#define kr__ 83
+#define kF__ 84
+#define kR__ 85
+#define kT__ 86
+#define ku__ 87 /* key up */
+#define ke__ 88
+#define ks__ 89
+#define l0__ 90
+#define l1__ 91
+#define la__ 92
+#define l2__ 93
+#define l3__ 94
+#define l4__ 95
+#define l5__ 96
+#define l6__ 97
+#define l7__ 98
+#define l8__ 99
+#define l9__ 100
+#define mo__ 101
+#define mm__ 102
+#define nw__ 103
+#define pc__ 104
+#define DC__ 105
+#define DL__ 106
+#define DO__ 107
+#define IC__ 118
+#define SF__ 109
+#define AL__ 110
+#define LE__ 111
+#define RI__ 112
+#define SR__ 113
+#define UP__ 114
+#define pk__ 115
+#define pl__ 116
+#define px__ 117
+#define ps__ 118
+#define pf__ 119
+#define po__ 120
+#define rp__ 121
+#define r1__ 122
+#define r2__ 123
+#define r3__ 124
+#define rf__ 125
+#define rc__ 126
+#define cv__ 127
+#define sc__ 128
+#define sf__ 129
+#define sr__ 130
+#define sa__ 131 /* sgr */
+#define st__ 132
+#define wi__ 133
+#define ta__ 134
+#define ts__ 135
+#define uc__ 136
+#define hu__ 137
+#define iP__ 138
+#define K1__ 139
+#define K2__ 140
+#define K3__ 141
+#define K4__ 142
+#define K5__ 143
+#define pO__ 144
+#define ml__ 145
+#define mu__ 146
+#define rmp__ 145
+#define acsc__ 146
+#define pln__ 147
+#define kcbt__ 148
+#define smxon__ 149
+#define rmxon__ 150
+#define smam__ 151
+#define rmam__ 152
+#define xonc__ 153
+#define xoffc__ 154
+#define enacs__ 155
+#define smln__ 156
+#define rmln__ 157
+#define kbeg__ 158
+#define kcan__ 159
+#define kclo__ 160
+#define kcmd__ 161
+#define kcpy__ 162
+#define kcrt__ 163
+#define kend__ 164
+#define kent__ 165
+#define kext__ 166
+#define kfnd__ 167
+#define khlp__ 168
+#define kmrk__ 169
+#define kmsg__ 170
+#define kmov__ 171
+#define knxt__ 172
+#define kopn__ 173
+#define kopt__ 174
+#define kprv__ 175
+#define kprt__ 176
+#define krdo__ 177
+#define kref__ 178
+#define krfr__ 179
+#define krpl__ 180
+#define krst__ 181
+#define kres__ 182
+#define ksav__ 183
+#define kspd__ 184
+#define kund__ 185
+#define kBEG__ 186
+#define kCAN__ 187
+#define kCMD__ 188
+#define kCPY__ 189
+#define kCRT__ 190
+#define kDC__ 191
+#define kDL__ 192
+#define kslt__ 193
+#define kEND__ 194
+#define kEOL__ 195
+#define kEXT__ 196
+#define kFND__ 197
+#define kHLP__ 198
+#define kHOM__ 199
+#define kIC__ 200
+#define kLFT__ 201
+#define kMSG__ 202
+#define kMOV__ 203
+#define kNXT__ 204
+#define kOPT__ 205
+#define kPRV__ 206
+#define kPRT__ 207
+#define kRDO__ 208
+#define kRPL__ 209
+#define kRIT__ 210
+#define kRES__ 211
+#define kSAV__ 212
+#define kSPD__ 213
+#define kUND__ 214
+#define rfi__ 215
+#define kf11__ 216
+#define kf12__ 217
+#define kf13__ 218
+#define kf14__ 219
+#define kf15__ 220
+#define kf16__ 221
+#define kf17__ 222
+#define kf18__ 223
+#define kf19__ 224
+#define kf20__ 225
+#define kf21__ 226
+#define kf22__ 227
+#define kf23__ 228
+#define kf24__ 229
+#define kf25__ 230
+#define kf26__ 231
+#define kf27__ 232
+#define kf28__ 233
+#define kf29__ 234
+#define kf30__ 235
+#define kf31__ 236
+#define kf32__ 237
+#define kf33__ 238
+#define kf34__ 239
+#define kf35__ 240
+#define kf36__ 241
+#define kf37__ 242
+#define kf38__ 243
+#define kf39__ 244
+#define kf40__ 245
+#define kf41__ 246
+#define kf42__ 247
+#define kf43__ 248
+#define kf44__ 249
+#define kf45__ 250
+#define kf46__ 251
+#define kf47__ 252
+#define kf48__ 253
+#define kf49__ 254
+#define kf50__ 255
+#define kf51__ 256
+#define kf52__ 257
+#define kf53__ 258
+#define kf54__ 259
+#define kf55__ 260
+#define kf56__ 261
+#define kf57__ 262
+#define kf58__ 263
+#define kf59__ 264
+#define kf60__ 265
+#define kf61__ 266
+#define kf62__ 267
+#define kf63__ 268
+#define el1__ 269
+#define mgc__ 270
+#define smgl__ 271
+#define smgr__ 272
+
+#ifdef CAP
+char *Boolean_names[] = {
+"bw", "am", "xb", "xs", "xn", "eo", "gn", "hc", "km", "hs", "in", "da", "db",
+"mi", "ms", "os", "es", "xt", "hz", "ul", "xo", "HC", "nx", "NR", "NP", "5i"
+};
+
+char *Number_names[] = {
+"co#", "it#", "li#", "lm#", "sg#", "pb#", "vt#", "ws#", "Nl#", "lh#", "lw#"
+};
+
+char *String_names[] = {
+"bt=", "bl=", "cr=", "cs=", "ct=", "cl=", "ce=", "cd=", "ch=", "CC=", "cm=",
+"do=", "ho=", "vi=", "le=", "CM=", "ve=", "nd=", "ll=", "up=", "vs=", "dc=",
+"dl=", "ds=", "hd=", "as=", "mb=", "md=", "ti=", "dm=", "mh=", "im=", "mk=",
+"mp=", "mr=", "so=", "us=", "ec=", "ae=", "me=", "te=", "ed=", "ei=", "se=",
+"ue=", "vb=", "ff=", "fs=", "i1=", "i2=", "i3=", "if=", "ic=", "al=", "ip=",
+"kb=", "ka=", "kC=", "kt=", "kD=", "kL=", "kd=", "kM=", "kE=", "kS=", "k0=",
+"k1=", "k;=", "k2=", "k3=", "k4=", "k5=", "k6=", "k7=", "k8=", "k9=", "kh=",
+"kI=", "kA=", "kl=", "kH=", "kN=", "kP=", "kr=", "kF=", "kR=", "kT=", "ku=",
+"ke=", "ks=", "l0=", "l1=", "la=", "l2=", "l3=", "l4=", "l5=", "l6=", "l7=",
+"l8=", "l9=", "mo=", "mm=", "nw=", "pc=", "DC=", "DL=", "DO=", "IC=", "SF=",
+"AL=", "LE=", "RI=", "SR=", "UP=", "pk=", "pl=", "px=", "ps=", "pf=", "po=",
+"rp=", "r1=", "r2=", "r3=", "rf=", "rc=", "cv=", "sc=", "sf=", "sr=", "sa=",
+"st=", "wi=", "ta=", "ts=", "uc=", "hu=", "iP=", "K1=", "K3=", "K2=", "K4=",
+"K5=", "pO=", "rP=", "ac=", "pn=", "kB=", "SX=", "RX=", "SA=", "RA=", "XN=",
+"XF=", "eA=", "LO=", "LF=", "@1=", "@2=", "@3=", "@4=", "@5=", "@6=", "@7=",
+"@8=", "@9=", "@0=", "%1=", "%2=", "%3=", "%4=", "%5=", "%6=", "%7=", "%8=",
+"%9=", "%0=", "&1=", "&2=", "&3=", "&4=", "&5=", "&6=", "&7=", "&8=", "&9=",
+"&0=", "*1=", "*2=", "*3=", "*4=", "*5=", "*6=", "*7=", "*8=", "*9=", "*0=",
+"#1=", "#2=", "#3=", "#4=", "%a=", "%b=", "%c=", "%d=", "%e=", "%f=", "%g=",
+"%h=", "%i=", "%j=", "!1=", "!2=", "!3=", "RF=", "F1=", "F2=", "F3=", "F4=",
+"F5=", "F6=", "F7=", "F8=", "F9=", "FA=", "FB=", "FC=", "FD=", "FE=", "FF=",
+"FG=", "FH=", "FI=", "FJ=", "FK=", "FL=", "FM=", "FN=", "FO=", "FP=", "FQ=",
+"FR=", "FS=", "FT=", "FU=", "FV=", "FW=", "FX=", "FY=", "FZ=", "Fa=", "Fb=",
+"Fc=", "Fd=", "Fe=", "Ff=", "Fg=", "Fh=", "Fi=", "Fj=", "Fk=", "Fl=", "Fm=",
+"Fn=", "Fo=", "Fp=", "Fq=", "Fr=", "cb=", "MC=", "ML=", "MR="
+};
+#endif
+
+char *new_curse = "October 1987";
+
+char in_buff[100]; /* buffer for ungetch */
+int bufp; /* next free position in in_buff */
+
+char *TERMINAL_TYPE = NULL; /* terminal type to be gotten from environment */
+int CFOUND = FALSE;
+int Data_Line_len = 0;
+int Max_Key_len; /* max length of a sequence sent by a key */
+char *Data_Line = NULL;
+char *TERM_PATH = NULL;
+char *TERM_data_ptr = NULL;
+char *Term_File_name = NULL; /* name of file containing terminal description */
+FILE *TFP; /* file pointer to file with terminal des. */
+int Fildes; /* file descriptor for terminfo file */
+int STAND = FALSE; /* is standout mode activated? */
+int TERM_INFO = FALSE; /* is terminfo being used (TRUE), or termcap (FALSE) */
+int Time_Out; /* set when time elapsed while trying to read function key */
+int Curr_x; /* current x position on screen */
+int Curr_y; /* current y position on the screen */
+int LINES;
+int COLS;
+int Move_It; /* flag to move cursor if magic cookie glitch */
+int initialized = FALSE; /* tells whether new_curse is initialized */
+float speed;
+float chars_per_millisecond;
+int Repaint_screen; /* if an operation to change screen impossible, repaint screen */
+int Intr; /* storeage for interrupt character */
+int Parity; /* 0 = no parity, 1 = odd parity, 2 = even parity */
+int Noblock; /* for BSD systems */
+int Num_bits; /* number of bits per character */
+int Flip_Bytes; /* some systems have byte order reversed */
+int interrupt_flag = FALSE; /* set true if SIGWINCH received */
+
+#ifndef CAP
+char *Strings;
+#endif
+
+struct KEYS {
+ int length; /* length of string sent by key */
+ char *string; /* string sent by key */
+ int value; /* CURSES value of key (9-bit) */
+ };
+
+struct KEY_STACK {
+ struct KEYS *element;
+ struct KEY_STACK *next;
+ };
+
+struct KEY_STACK *KEY_TOS = NULL;
+struct KEY_STACK *KEY_POINT;
+
+struct Parameters {
+ int value;
+ struct Parameters *next;
+ };
+
+int Key_vals[] = {
+ 0407, 0526, 0515, 0525, 0512, 0510, 0402, 0514, 0517, 0516, 0410, 0411,
+ 0422, 0412, 0413, 0414, 0415, 0416, 0417, 0420, 0421, 0406, 0513, 0511,
+ 0404, 0533, 0522, 0523, 0405, 0520, 0521, 0524, 0403,
+ 0534, 0535, 0536, 0537, 0540, 0541, 0542, 0543, 0544, 0545, 0546, 0547,
+ 0550, 0527, 0551, 0552, 0553, 0554, 0555, 0556, 0557, 0560, 0561, 0562,
+ 0532, 0563, 0564, 0565, 0566, 0567, 0570, 0571, 0627, 0630, 0572, 0573,
+ 0574, 0575, 0576, 0577, 0600, 0601, 0602, 0603, 0604, 0605, 0606, 0607,
+ 0610, 0611, 0612, 0613, 0614, 0615, 0616, 0617, 0620, 0621, 0622, 0623,
+ 0624, 0625, 0626, 0423, 0424, 0425, 0426, 0427, 0430, 0431,
+ 0432, 0433, 0434, 0435, 0436, 0437, 0440, 0441, 0442, 0443, 0444, 0445,
+ 0446, 0447, 0450, 0451, 0452, 0453, 0454, 0455, 0456, 0457, 0460, 0461,
+ 0462, 0463, 0464, 0465, 0466, 0467, 0470, 0471, 0472, 0473, 0474, 0475,
+ 0476, 0477, 0500, 0501, 0502, 0503, 0504, 0505, 0506, 0507
+};
+
+int attributes_set[9];
+
+#ifdef SYS5
+struct termio Terminal;
+struct termio Saved_tty;
+#else
+struct sgttyb Terminal;
+struct sgttyb Saved_tty;
+#endif
+
+char *tc_;
+
+int Booleans[128];
+int Numbers[128];
+char *String_table[1024];
+
+int *virtual_lines;
+
+static char nc_scrolling_ability = FALSE;
+
+#ifdef CAP
+
+#if __STDC__ || defined(__cplusplus)
+#define P_(s) s
+#else
+#define P_(s) ()
+#endif /* __STDC__ */
+
+int tc_Get_int P_((int));
+void CAP_PARSE P_((void));
+void Find_term P_((void));
+
+#undef P_
+
+#endif /* CAP */
+
+
+#ifndef __STDC__
+#ifndef HAS_STDLIB
+extern char *fgets();
+extern char *malloc();
+extern char *getenv();
+FILE *fopen(); /* declaration for open function */
+#endif /* HAS_STDLIB */
+#endif /* __STDC__ */
+
+#ifdef SIGWINCH
+
+/*
+ | Copy the contents of one window to another.
+ */
+
+void
+copy_window(origin, destination)
+WINDOW *origin, *destination;
+{
+ int row, column;
+ struct _line *orig, *dest;
+
+ orig = origin->first_line;
+ dest = destination->first_line;
+
+ for (row = 0;
+ row < (min(origin->Num_lines, destination->Num_lines));
+ row++)
+ {
+ for (column = 0;
+ column < (min(origin->Num_cols, destination->Num_cols));
+ column++)
+ {
+ dest->row[column] = orig->row[column];
+ dest->attributes[column] = orig->attributes[column];
+ }
+ dest->changed = orig->changed;
+ dest->scroll = orig->scroll;
+ dest->last_char = min(orig->last_char, destination->Num_cols);
+ orig = orig->next_screen;
+ dest = dest->next_screen;
+ }
+ destination->LX = min((destination->Num_cols - 1), origin->LX);
+ destination->LY = min((destination->Num_lines - 1), origin->LY);
+ destination->Attrib = origin->Attrib;
+ destination->scroll_up = origin->scroll_up;
+ destination->scroll_down = origin->scroll_down;
+ destination->SCROLL_CLEAR = origin->SCROLL_CLEAR;
+}
+
+void
+reinitscr(foo)
+int foo;
+{
+ WINDOW *local_virt;
+ WINDOW *local_std;
+ WINDOW *local_cur;
+
+ signal(SIGWINCH, reinitscr);
+#ifdef TIOCGWINSZ
+ if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
+ {
+ if (ws.ws_row == LINES && ws.ws_col == COLS)
+ return;
+ if (ws.ws_row > 0)
+ LINES = ws.ws_row;
+ if (ws.ws_col > 0)
+ COLS = ws.ws_col;
+ }
+#endif /* TIOCGWINSZ */
+ local_virt = newwin(LINES, COLS, 0, 0);
+ local_std = newwin(LINES, COLS, 0, 0);
+ local_cur = newwin(LINES, COLS, 0, 0);
+ copy_window(virtual_scr, local_virt);
+ copy_window(stdscr, local_std);
+ copy_window(curscr, local_cur);
+ delwin(virtual_scr);
+ delwin(stdscr);
+ delwin(curscr);
+ virtual_scr = local_virt;
+ stdscr = local_std;
+ curscr = local_cur;
+ free(virtual_lines);
+ virtual_lines = (int *) malloc(LINES * (sizeof(int)));
+ interrupt_flag = TRUE;
+}
+#endif /* SIGWINCH */
+
+void
+initscr() /* initialize terminal for operations */
+{
+ int value;
+ char *lines_string;
+ char *columns_string;
+#ifdef CAP
+ char *pointer;
+#endif /* CAP */
+
+#ifdef DIAG
+printf("starting initscr \n");fflush(stdout);
+#endif
+ if (initialized)
+ return;
+#ifdef BSD_SELECT
+ setbuf(stdin, NULL);
+#endif /* BSD_SELECT */
+ Flip_Bytes = FALSE;
+ Parity = 0;
+ Time_Out = FALSE;
+ bufp = 0;
+ Move_It = FALSE;
+ Noblock = FALSE;
+#ifdef SYS5
+ value = ioctl(0, TCGETA, &Terminal);
+ if (Terminal.c_cflag & PARENB)
+ {
+ if (Terminal.c_cflag & PARENB)
+ Parity = 1;
+ else
+ Parity = 2;
+ }
+ if ((Terminal.c_cflag & CS8) == CS8)
+ {
+ Num_bits = 8;
+ }
+ else if ((Terminal.c_cflag & CS7) == CS7)
+ Num_bits = 7;
+ else if ((Terminal.c_cflag & CS6) == CS6)
+ Num_bits = 6;
+ else
+ Num_bits = 5;
+ value = Terminal.c_cflag & 037;
+ switch (value) {
+ case 01: speed = 50.0;
+ break;
+ case 02: speed = 75.0;
+ break;
+ case 03: speed = 110.0;
+ break;
+ case 04: speed = 134.5;
+ break;
+ case 05: speed = 150.0;
+ break;
+ case 06: speed = 200.0;
+ break;
+ case 07: speed = 300.0;
+ break;
+ case 010: speed = 600.0;
+ break;
+ case 011: speed = 900.0;
+ break;
+ case 012: speed = 1200.0;
+ break;
+ case 013: speed = 1800.0;
+ break;
+ case 014: speed = 2400.0;
+ break;
+ case 015: speed = 3600.0;
+ break;
+ case 016: speed = 4800.0;
+ break;
+ case 017: speed = 7200.0;
+ break;
+ case 020: speed = 9600.0;
+ break;
+ case 021: speed = 19200.0;
+ break;
+ case 022: speed = 38400.0;
+ break;
+ default: speed = 0.0;
+ }
+#else
+ value = ioctl(0, TIOCGETP, &Terminal);
+ if (Terminal.sg_flags & EVENP)
+ Parity = 2;
+ else if (Terminal.sg_flags & ODDP)
+ Parity = 1;
+ value = Terminal.sg_ospeed;
+ switch (value) {
+ case 01: speed = 50.0;
+ break;
+ case 02: speed = 75.0;
+ break;
+ case 03: speed = 110.0;
+ break;
+ case 04: speed = 134.5;
+ break;
+ case 05: speed = 150.0;
+ break;
+ case 06: speed = 200.0;
+ break;
+ case 07: speed = 300.0;
+ break;
+ case 010: speed = 600.0;
+ break;
+ case 011: speed = 1200.0;
+ break;
+ case 012: speed = 1800.0;
+ break;
+ case 013: speed = 2400.0;
+ break;
+ case 014: speed = 4800.0;
+ break;
+ case 015: speed = 9600.0;
+ break;
+ default: speed = 0.0;
+ }
+#endif
+ chars_per_millisecond = (0.001 * speed) / 8.0;
+ TERMINAL_TYPE = getenv("TERM");
+ if (TERMINAL_TYPE == NULL)
+ {
+ printf("unknown terminal type\n");
+ exit(0);
+ }
+#ifndef CAP
+ Fildes = -1;
+ TERM_PATH = getenv("TERMINFO");
+ if (TERM_PATH != NULL)
+ {
+ Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
+ Term_File_name = malloc(Data_Line_len);
+ sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
+ Fildes = open(Term_File_name, O_RDONLY);
+ }
+ if (Fildes == -1)
+ {
+ TERM_PATH = "/usr/lib/terminfo";
+ Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
+ Term_File_name = malloc(Data_Line_len);
+ sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
+ Fildes = open(Term_File_name, O_RDONLY);
+ }
+ if (Fildes == -1)
+ {
+ TERM_PATH = "/usr/share/lib/terminfo";
+ Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
+ Term_File_name = malloc(Data_Line_len);
+ sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
+ Fildes = open(Term_File_name, O_RDONLY);
+ }
+ if (Fildes == -1)
+ {
+ free(Term_File_name);
+ Term_File_name = NULL;
+ }
+ else
+ TERM_INFO = INFO_PARSE();
+#else
+ /*
+ | termcap information can be in the TERMCAP env variable, if so
+ | use that, otherwise check the /etc/termcap file
+ */
+ if ((pointer = Term_File_name = getenv("TERMCAP")) != NULL)
+ {
+ if (*Term_File_name != '/')
+ Term_File_name = "/etc/termcap";
+ }
+ else
+ {
+ Term_File_name = "/etc/termcap";
+ }
+ if ((TFP = fopen(Term_File_name, "r")) == NULL)
+ {
+ printf("unable to open /etc/termcap file \n");
+ exit(0);
+ }
+ for (value = 0; value < 1024; value++)
+ String_table[value] = NULL;
+ for (value = 0; value < 128; value++)
+ Booleans[value] = 0;
+ for (value = 0; value < 128; value++)
+ Numbers[value] = 0;
+ Data_Line = malloc(512);
+ if (pointer && *pointer != '/')
+ {
+ TERM_data_ptr = pointer;
+ CAP_PARSE();
+ }
+ else
+ {
+ Find_term();
+ CAP_PARSE();
+ }
+#endif
+ if (String_table[pc__] == NULL)
+ String_table[pc__] = "\0";
+ if ((String_table[cm__] == NULL) || (Booleans[hc__]))
+ {
+ fprintf(stderr, "sorry, unable to use this terminal type for screen editing\n");
+ exit(0);
+ }
+ Key_Get();
+ LINES = Numbers[li__];
+ COLS = Numbers[co__];
+ if ((lines_string = getenv("LINES")) != NULL)
+ {
+ value = atoi(lines_string);
+ if (value > 0)
+ LINES = value;
+ }
+ if ((columns_string = getenv("COLUMNS")) != NULL)
+ {
+ value = atoi(columns_string);
+ if (value > 0)
+ COLS = value;
+ }
+#ifdef TIOCGWINSZ
+ /*
+ | get the window size
+ */
+ if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
+ {
+ if (ws.ws_row > 0)
+ LINES = ws.ws_row;
+ if (ws.ws_col > 0)
+ COLS = ws.ws_col;
+ }
+#endif
+ virtual_scr = newwin(LINES, COLS, 0, 0);
+ stdscr = newwin(LINES, COLS, 0, 0);
+ curscr = newwin(LINES, COLS, 0, 0);
+ wmove(stdscr, 0, 0);
+ werase(stdscr);
+ Repaint_screen = TRUE;
+ initialized = TRUE;
+ virtual_lines = (int *) malloc(LINES * (sizeof(int)));
+
+#ifdef SIGWINCH
+ /*
+ | reset size of windows and LINES and COLS if term window
+ | changes size
+ */
+ signal(SIGWINCH, reinitscr);
+#endif /* SIGWINCH */
+
+ /*
+ | check if scrolling is available
+ */
+
+ nc_scrolling_ability = ((String_table[al__] != NULL) &&
+ (String_table[dl__])) || ((String_table[cs__])
+ && (String_table[sr__]));
+
+}
+
+#ifndef CAP
+int
+Get_int() /* get a two-byte integer from the terminfo file */
+{
+ int High_byte;
+ int Low_byte;
+ int temp;
+
+ Low_byte = *((unsigned char *) TERM_data_ptr++);
+ High_byte = *((unsigned char *) TERM_data_ptr++);
+ if (Flip_Bytes)
+ {
+ temp = Low_byte;
+ Low_byte = High_byte;
+ High_byte = temp;
+ }
+ if ((High_byte == 255) && (Low_byte == 255))
+ return (-1);
+ else
+ return(Low_byte + (High_byte * 256));
+}
+
+int
+INFO_PARSE() /* parse off the data in the terminfo data file */
+{
+ int offset;
+ int magic_number = 0;
+ int counter = 0;
+ int Num_names = 0;
+ int Num_bools = 0;
+ int Num_ints = 0;
+ int Num_strings = 0;
+ int string_table_len = 0;
+ char *temp_ptr;
+
+ TERM_data_ptr = Data_Line = malloc((10240 * (sizeof(char))));
+ Data_Line_len = read(Fildes, Data_Line, 10240);
+ if ((Data_Line_len >= 10240) || (Data_Line_len < 0))
+ return(0);
+ /*
+ | get magic number
+ */
+ magic_number = Get_int();
+ /*
+ | if magic number not right, reverse byte order and check again
+ */
+ if (magic_number != 282)
+ {
+ Flip_Bytes = TRUE;
+ TERM_data_ptr--;
+ TERM_data_ptr--;
+ magic_number = Get_int();
+ if (magic_number != 282)
+ return(0);
+ }
+ /*
+ | get the number of each type in the terminfo data file
+ */
+ Num_names = Get_int();
+ Num_bools = Get_int();
+ Num_ints = Get_int();
+ Num_strings = Get_int();
+ string_table_len = Get_int();
+ Strings = malloc(string_table_len);
+ while (Num_names > 0)
+ {
+ TERM_data_ptr++;
+ Num_names--;
+ }
+ counter = 0;
+ while (Num_bools)
+ {
+ Num_bools--;
+ Booleans[counter++] = *TERM_data_ptr++;
+ }
+ if (((unsigned int) TERM_data_ptr) & 1) /* force alignment */
+ TERM_data_ptr++;
+ counter = 0;
+ while (Num_ints)
+ {
+ Num_ints--;
+ Numbers[counter] = Get_int();
+ counter++;
+ }
+ temp_ptr = TERM_data_ptr + Num_strings + Num_strings;
+ memcpy(Strings, temp_ptr, string_table_len);
+ counter = bt__;
+ while (Num_strings)
+ {
+ Num_strings--;
+ if ((offset=Get_int()) != -1)
+ {
+ if (String_table[counter] == NULL)
+ String_table[counter] = Strings + offset;
+ }
+ else
+ String_table[counter] = NULL;
+ counter++;
+ }
+ close(Fildes);
+ free(Data_Line);
+ return(TRUE);
+}
+#endif /* ifndef CAP */
+
+int
+AtoI() /* convert ascii text to integers */
+{
+ int Temp;
+
+ Temp = 0;
+ while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
+ {
+ Temp = (Temp * 10) + (*TERM_data_ptr - '0');
+ TERM_data_ptr++;
+ }
+ return(Temp);
+}
+
+void
+Key_Get() /* create linked list with all key sequences obtained from terminal database */
+{
+ int Counter;
+ int Klen;
+ int key_def;
+ struct KEY_STACK *Spoint;
+
+ Max_Key_len = 0;
+ Counter = 0;
+ key_def = kb__;
+ while (key_def <= kf63__)
+ {
+ if (key_def == ke__)
+ key_def = K1__;
+ else if (key_def == (K5__ + 1))
+ key_def = kcbt__;
+ else if (key_def == (kcbt__ + 1))
+ key_def = kbeg__;
+ else if (key_def == (kUND__ + 1))
+ key_def = kf11__;
+ if (String_table[key_def] != NULL)
+ {
+ if (KEY_TOS == NULL)
+ Spoint = KEY_TOS = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
+ else
+ {
+ Spoint = KEY_TOS;
+ while (Spoint->next != NULL)
+ Spoint = Spoint->next;
+ Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
+ Spoint = Spoint->next;
+ }
+ Spoint->next = NULL;
+ Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
+ Spoint->element->string = String_table[key_def];
+ Spoint->element->length = strlen(String_table[key_def]);
+ Spoint->element->value = Key_vals[Counter];
+ Klen = strlen(Spoint->element->string);
+ if (Klen > Max_Key_len)
+ Max_Key_len = Klen;
+ /*
+ | Some terminal types accept keystrokes of the form
+ | \E[A and \EOA, substituting '[' for 'O'. Make a
+ | duplicate of such key strings (since the
+ | database will only have one version) so new_curse
+ | can understand both.
+ */
+ if ((Spoint->element->length > 1) &&
+ ((String_table[key_def][1] == '[') ||
+ (String_table[key_def][1] == 'O')))
+ {
+ Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
+ Spoint = Spoint->next;
+ Spoint->next = NULL;
+ Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
+ Spoint->element->length = strlen(String_table[key_def]);
+ Spoint->element->string = malloc(Spoint->element->length + 1);
+ strcpy(Spoint->element->string, String_table[key_def]);
+ Spoint->element->value = Key_vals[Counter];
+ Klen = strlen(Spoint->element->string);
+ if (Klen > Max_Key_len)
+ Max_Key_len = Klen;
+
+ if (String_table[key_def][1] == '[')
+ Spoint->element->string[1] = 'O';
+ else
+ Spoint->element->string[1] = '[';
+ }
+ }
+ key_def++;
+ Counter++;
+ }
+}
+
+#ifdef CAP
+char *
+String_Get(param) /* read the string */
+char *param;
+{
+ char *String;
+ char *Temp;
+ int Counter;
+
+ if (param == NULL)
+ {
+ while (*TERM_data_ptr != '=')
+ TERM_data_ptr++;
+ Temp = ++TERM_data_ptr;
+ Counter = 1;
+ while ((*Temp != ':') && (*Temp != (char)NULL))
+ {
+ Counter++;
+ Temp++;
+ }
+ if (Counter == 1) /* no data */
+ return(NULL);
+ String = Temp = malloc(Counter);
+ while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL))
+ {
+ if (*TERM_data_ptr == '\\')
+ {
+ TERM_data_ptr++;
+ if (*TERM_data_ptr == 'n')
+ *Temp = '\n';
+ else if (*TERM_data_ptr == 't')
+ *Temp = '\t';
+ else if (*TERM_data_ptr == 'b')
+ *Temp = '\b';
+ else if (*TERM_data_ptr == 'r')
+ *Temp = '\r';
+ else if (*TERM_data_ptr == 'f')
+ *Temp = '\f';
+ else if ((*TERM_data_ptr == 'e') || (*TERM_data_ptr == 'E'))
+ *Temp = '\033'; /* escape */
+ else if (*TERM_data_ptr == '\\')
+ *Temp = '\\';
+ else if (*TERM_data_ptr == '\'')
+ *Temp = '\'';
+ else if ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
+ {
+ Counter = 0;
+ while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
+ {
+ Counter = (8 * Counter) + (*TERM_data_ptr - '0');
+ TERM_data_ptr++; /* ? */
+ }
+ *Temp = Counter;
+ TERM_data_ptr--;
+ }
+ TERM_data_ptr++;
+ Temp++;
+ }
+ else if (*TERM_data_ptr == '^')
+ {
+ TERM_data_ptr++;
+ if ((*TERM_data_ptr >= '@') && (*TERM_data_ptr <= '_'))
+ *Temp = *TERM_data_ptr - '@';
+ else if (*TERM_data_ptr == '?')
+ *Temp = 127;
+ TERM_data_ptr++;
+ Temp++;
+ }
+ else
+ *Temp++ = *TERM_data_ptr++;
+ }
+ *Temp = (char)NULL;
+ param = String;
+ }
+ else
+ {
+ while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != ':'))
+ TERM_data_ptr++;
+ }
+ return(param);
+}
+
+int
+tc_Get_int(param) /* read the integer */
+int param;
+{
+ int Itemp;
+
+ if (param == 0)
+ {
+ while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '#'))
+ TERM_data_ptr++;
+ TERM_data_ptr++;
+ Itemp = AtoI();
+ param = Itemp;
+ }
+ else
+ {
+ while (*TERM_data_ptr != ':')
+ TERM_data_ptr++;
+ }
+ return(param);
+}
+
+void
+Find_term() /* find terminal description in termcap file */
+{
+ char *Name;
+ char *Ftemp;
+
+ Ftemp = Name = malloc(strlen(TERMINAL_TYPE + 1) + 1);
+ strcpy(Name, TERMINAL_TYPE);
+ while (*Ftemp != (char)NULL)
+ Ftemp++;
+ *Ftemp++ = '|';
+ *Ftemp = (char)NULL;
+ CFOUND = FALSE;
+ Data_Line_len = strlen(TERMINAL_TYPE) + 1;
+ while ((!CFOUND) && ((TERM_data_ptr=fgets(Data_Line, 512, TFP)) != NULL))
+ {
+ if ((*TERM_data_ptr != ' ') && (*TERM_data_ptr != '\t') && (*TERM_data_ptr != '#'))
+ {
+ while ((!CFOUND) && (*TERM_data_ptr != (char)NULL))
+ {
+ CFOUND = !strncmp(TERM_data_ptr, Name, Data_Line_len);
+ while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '|') && (*TERM_data_ptr != '#') && (*TERM_data_ptr != ':'))
+ TERM_data_ptr++;
+ if (*TERM_data_ptr == '|')
+ TERM_data_ptr++;
+ else if (!CFOUND)
+ *TERM_data_ptr = (char)NULL;
+ }
+ }
+ }
+ if (!CFOUND)
+ {
+ printf("terminal type %s not found\n", TERMINAL_TYPE);
+ exit(0);
+ }
+}
+
+void
+CAP_PARSE() /* parse off the data in the termcap data file */
+{
+ int offset;
+ int found;
+
+ do
+ {
+ while (*TERM_data_ptr != (char)NULL)
+ {
+ for (found = FALSE, offset = 0; (!found) && (offset < 26); offset++)
+ {
+ if (!strncmp(TERM_data_ptr, Boolean_names[offset], 2))
+ {
+ found = TRUE;
+ Booleans[offset] = TRUE;
+ }
+ }
+ if (!found)
+ {
+ for (found = FALSE, offset = 0; (!found) && (offset < lw__); offset++)
+ {
+ if (!strncmp(TERM_data_ptr, Number_names[offset], 3))
+ {
+ found = TRUE;
+ Numbers[offset] = tc_Get_int(Numbers[offset]);
+ }
+ }
+ }
+ if (!found)
+ {
+ for (found = FALSE, offset = 0; (!found) && (offset < smgr__); offset++)
+ {
+ if (!strncmp(TERM_data_ptr, String_names[offset], 3))
+ {
+ found = TRUE;
+ String_table[offset] = String_Get(String_table[offset]);
+ }
+ }
+ }
+
+ if (!strncmp(TERM_data_ptr, "tc=", 3))
+ tc_ = String_Get(NULL);
+ while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL))
+ TERM_data_ptr++;
+ if (*TERM_data_ptr == ':')
+ TERM_data_ptr++;
+ }
+ } while (((TERM_data_ptr = fgets(Data_Line, 512, TFP)) != NULL) && ((*TERM_data_ptr == ' ') || (*TERM_data_ptr == '\t')));
+ if (tc_ != NULL)
+ {
+ TERMINAL_TYPE = tc_;
+ rewind(TFP);
+ Find_term();
+ free(tc_);
+ tc_ = NULL;
+ CAP_PARSE();
+ }
+ else
+ fclose(TFP);
+}
+#endif /* ifdef CAP */
+
+struct _line *
+Screenalloc(columns)
+int columns;
+{
+ int i;
+ struct _line *tmp;
+
+ tmp = (struct _line *) malloc(sizeof (struct _line));
+ tmp->row = malloc(columns + 1);
+ tmp->attributes = malloc(columns + 1);
+ tmp->prev_screen = NULL;
+ tmp->next_screen = NULL;
+ for (i = 0; i < columns; i++)
+ {
+ tmp->row[i] = ' ';
+ tmp->attributes[i] = (char) NULL;
+ }
+ tmp->scroll = tmp->changed = FALSE;
+ tmp->row[0] = (char) NULL;
+ tmp->attributes[0] = (char) NULL;
+ tmp->row[columns] = (char) NULL;
+ tmp->attributes[columns] = (char) NULL;
+ tmp->last_char = 0;
+ return(tmp);
+}
+
+WINDOW *newwin(lines, cols, start_l, start_c)
+int lines, cols; /* number of lines and columns to be in window */
+int start_l, start_c; /* starting line and column to be inwindow */
+{
+ WINDOW *Ntemp;
+ struct _line *temp_screen;
+ int i;
+
+ Ntemp = (WINDOW *) malloc(sizeof(WINDOW));
+ Ntemp->SR = start_l;
+ Ntemp->SC = start_c;
+ Ntemp->Num_lines = lines;
+ Ntemp->Num_cols = cols;
+ Ntemp->LX = 0;
+ Ntemp->LY = 0;
+ Ntemp->scroll_down = Ntemp->scroll_up = 0;
+ Ntemp->SCROLL_CLEAR = FALSE;
+ Ntemp->Attrib = FALSE;
+ Ntemp->first_line = temp_screen = Screenalloc(cols);
+ Ntemp->first_line->number = 0;
+ for (i = 1; i < lines; i++)
+ {
+ temp_screen->next_screen = Screenalloc(cols);
+ temp_screen->next_screen->number = i;
+ temp_screen->next_screen->prev_screen = temp_screen;
+ temp_screen = temp_screen->next_screen;
+ }
+ Ntemp->first_line->prev_screen = NULL;
+ temp_screen->next_screen = NULL;
+ return(Ntemp);
+}
+
+#ifdef CAP
+void
+Cap_Out(string, p_list, place) /* interpret the output string if necessary */
+char *string;
+int p_list[]; /* stack of values */
+int place; /* place keeper of top of stack */
+{
+ char *Otemp; /* temporary string pointer to parse output */
+ int delay;
+ int p1, p2, temp;
+ float chars;
+
+ if (string == NULL)
+ return;
+
+ if (p_list != NULL)
+ {
+ p1 = p_list[--place];
+ p2 = p_list[--place];
+ }
+ delay = 0;
+ Otemp = string;
+ if ((*Otemp >= '0') && (*Otemp <= '9'))
+ {
+ delay = atoi(Otemp);
+ while ((*Otemp >= '0') && (*Otemp <= '9'))
+ Otemp++;
+ if (*Otemp == '*')
+ Otemp++;
+ }
+ while (*Otemp != (char)NULL)
+ {
+ if (*Otemp == '%')
+ {
+ Otemp++;
+ if ((*Otemp == 'd') || (*Otemp == '2') || (*Otemp == '3') || (*Otemp == '.') || (*Otemp == '+'))
+ {
+ if (*Otemp == 'd')
+ printf("%d", p1);
+ else if (*Otemp == '2')
+ printf("%02d", p1);
+ else if (*Otemp == '3')
+ printf("%03d", p1);
+ else if (*Otemp == '+')
+ {
+ Otemp++;
+ p1 += *Otemp;
+ putchar(p1);
+ }
+ else if (*Otemp == '.')
+ putchar(p1);
+ p1 = p2;
+ p2 = 0;
+ }
+ else if (*Otemp == '>')
+ {
+ Otemp++;
+ if (p1 > *Otemp)
+ {
+ Otemp++;
+ p1 += *Otemp;
+ }
+ else
+ Otemp++;
+ }
+ else if (*Otemp == 'r')
+ {
+ temp = p1;
+ p1 = p2;
+ p2 = temp;
+ }
+ else if (*Otemp == 'i')
+ {
+ p1++;
+ p2++;
+ }
+ else if (*Otemp == '%')
+ putchar(*Otemp);
+ else if (*Otemp == 'n')
+ {
+ p1 ^= 0140;
+ p2 ^= 0140;
+ }
+ else if (*Otemp == 'B')
+ {
+ p1 = (16 * (p1/10)) + (p1 % 10);
+ p2 = (16 * (p2/10)) + (p2 % 10);
+ }
+ else if (*Otemp == 'D')
+ {
+ p1 = (p1 - 2 * (p1 % 16));
+ p2 = (p2 - 2 * (p2 % 16));
+ }
+ }
+ else
+ putchar (*Otemp);
+ Otemp++;
+ }
+ if (delay != 0)
+ {
+ chars = delay * chars_per_millisecond;
+ delay = chars;
+ if ((chars - delay) > 0.0)
+ delay++;
+ for (; delay > 0; delay--)
+ putchar(*String_table[pc__]);
+ }
+ fflush(stdout);
+}
+
+#else
+
+ char *Otemp; /* temporary string pointer to parse output */
+ float chars;
+ int p[10];
+ int variable[27];
+
+int
+Operation(Temp_Stack, place) /* handle conditional operations */
+int Temp_Stack[];
+int place;
+{
+ int temp;
+
+ if (*Otemp == 'd')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ printf("%d", temp);
+ }
+ else if (!strncmp(Otemp, "2d", 2))
+ {
+ temp = Temp_Stack[--place];
+ printf("%2d", temp);
+ Otemp++;
+ Otemp++;
+ }
+ else if (!strncmp(Otemp, "3d", 2))
+ {
+ temp = Temp_Stack[--place];
+ printf("%0d", temp);
+ Otemp++;
+ Otemp++;
+ }
+ else if (!strncmp(Otemp, "02d", 3))
+ {
+ temp = Temp_Stack[--place];
+ printf("%02d", temp);
+ Otemp++;
+ Otemp++;
+ Otemp++;
+ }
+ else if (!strncmp(Otemp, "03d", 3))
+ {
+ temp = Temp_Stack[--place];
+ printf("%03d", temp);
+ Otemp++;
+ Otemp++;
+ Otemp++;
+ }
+ else if (*Otemp == '+')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ temp += Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ }
+ else if (*Otemp == '-')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ temp -= Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ }
+ else if (*Otemp == '*')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ temp *= Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ }
+ else if (*Otemp == '/')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ temp /= Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ }
+ else if (*Otemp == 'm')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ temp %= Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ }
+ else if (*Otemp == '&')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ temp &= Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ }
+ else if (*Otemp == '|')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ temp |= Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ }
+ else if (*Otemp == '^')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ temp ^= Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ }
+ else if (*Otemp == '=')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ temp = (temp == Temp_Stack[--place]);
+ Temp_Stack[place++] = temp;
+ }
+ else if (*Otemp == '>')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ temp = temp > Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ }
+ else if (*Otemp == '<')
+ {
+ Otemp++;
+ temp = Temp_Stack[--place];
+ temp = temp < Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ }
+ else if (*Otemp == 'c')
+ {
+ Otemp++;
+ putchar(Temp_Stack[--place]);
+ }
+ else if (*Otemp == 'i')
+ {
+ Otemp++;
+ p[1]++;
+ p[2]++;
+ }
+ else if (*Otemp == '%')
+ {
+ putchar(*Otemp);
+ Otemp++;
+ }
+ else if (*Otemp == '!')
+ {
+ temp = ! Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ Otemp++;
+ }
+ else if (*Otemp == '~')
+ {
+ temp = ~Temp_Stack[--place];
+ Temp_Stack[place++] = temp;
+ Otemp++;
+ }
+ else if (*Otemp == 'p')
+ {
+ Otemp++;
+ Temp_Stack[place++] = p[*Otemp - '0'];
+ Otemp++;
+ }
+ else if (*Otemp == 'P')
+ {
+ Otemp++;
+ Temp_Stack[place++] = variable[*Otemp - 'a'];
+ Otemp++;
+ }
+ else if (*Otemp == 'g')
+ {
+ Otemp++;
+ variable[*Otemp - 'a'] = Temp_Stack[--place];
+ Otemp++;
+ }
+ else if (*Otemp == '\'')
+ {
+ Otemp++;
+ Temp_Stack[place++] = *Otemp;
+ Otemp++;
+ Otemp++;
+ }
+ else if (*Otemp == '{')
+ {
+ Otemp++;
+ temp = atoi(Otemp);
+ Temp_Stack[place++] = temp;
+ while (*Otemp != '}')
+ Otemp++;
+ Otemp++;
+ }
+ return(place);
+}
+
+void
+Info_Out(string, p_list, place) /* interpret the output string if necessary */
+char *string;
+int p_list[];
+int place;
+{
+ char *tchar;
+ int delay;
+ int temp;
+ int Cond_FLAG;
+ int EVAL;
+ int Cond_Stack[128];
+ int Cond_place;
+ int Stack[128];
+ int Top_of_stack;
+
+ if (string == NULL)
+ return;
+
+ Cond_FLAG = FALSE;
+ Cond_place = 0;
+ Top_of_stack = 0;
+ p[0] = 0;
+ p[1] = 0;
+ p[2] = 0;
+ p[3] = 0;
+ p[4] = 0;
+ p[5] = 0;
+ p[6] = 0;
+ p[7] = 0;
+ p[8] = 0;
+ p[9] = 0;
+ if (p_list != NULL)
+ {
+ for (temp = 1; (place != 0); temp++)
+ {
+ p[temp] = p_list[--place];
+ }
+ }
+ delay = 0;
+ Otemp = string;
+ while (*Otemp != (char) NULL)
+ {
+ if (*Otemp == '%')
+ {
+ Otemp++;
+ if ((*Otemp == '?') || (*Otemp == 't') || (*Otemp == 'e') || (*Otemp == ';'))
+ {
+ if (*Otemp == '?')
+ {
+ Otemp++;
+ Cond_FLAG = TRUE;
+ EVAL = TRUE;
+ while (EVAL)
+ {
+ /*
+ | find the end of the
+ | conditional statement
+ */
+ while ((strncmp(Otemp, "%t", 2)) && (*Otemp != (char) NULL))
+ {
+ /*
+ | move past '%'
+ */
+ Otemp++;
+ Cond_place = Operation(Cond_Stack, Cond_place);
+ }
+
+ /*
+ | if condition is true
+ */
+ if ((Cond_place > 0) && (Cond_Stack[Cond_place-1]))
+ {
+ /*
+ | end conditional
+ | parsing
+ */
+ EVAL = FALSE;
+ Otemp++;
+ Otemp++;
+ }
+ else /* condition is false */
+ {
+ /*
+ | find 'else' or end
+ | of if statement
+ */
+ while ((strncmp(Otemp, "%e", 2)) && (strncmp(Otemp, "%;", 2)) && (*Otemp != (char) NULL))
+ Otemp++;
+ /*
+ | if an 'else' found
+ */
+ if ((*Otemp != (char) NULL) && (!strncmp(Otemp, "%e", 2)))
+ {
+ Otemp++;
+ Otemp++;
+ tchar = Otemp;
+ /*
+ | check for 'then' part
+ */
+ while ((*tchar != (char) NULL) && (strncmp(tchar, "%t", 2)) && (strncmp(tchar, "%;", 2)))
+ tchar++;
+ /*
+ | if end of string
+ */
+ if (*tchar == (char) NULL)
+ {
+ EVAL = FALSE;
+ Cond_FLAG = FALSE;
+ Otemp = tchar;
+ }
+ /*
+ | if end of if found,
+ | set up to parse
+ | info
+ */
+ else if (!strncmp(tchar, "%;", 2))
+ EVAL = FALSE;
+ /*
+ | otherwise, check
+ | conditional in
+ | 'else'
+ */
+ }
+ /*
+ | if end of if found,
+ | get out of if
+ | statement
+ */
+ else if ((*Otemp != (char) NULL) && (!strncmp(Otemp, "%;", 2)))
+ {
+ EVAL = FALSE;
+ Otemp++;
+ Otemp++;
+ }
+ else /* Otemp == NULL */
+ {
+ EVAL = FALSE;
+ Cond_FLAG = FALSE;
+ }
+ }
+ }
+ }
+ else
+ {
+ Otemp++;
+ Cond_FLAG = FALSE;
+ if (*Otemp != ';')
+ {
+ while ((*Otemp != (char) NULL) && (strncmp(Otemp, "%;", 2)))
+ Otemp++;
+ if (*Otemp != (char) NULL)
+ {
+ Otemp++;
+ Otemp++;
+ }
+ }
+ else
+ Otemp++;
+ }
+ }
+ else
+ {
+ Top_of_stack = Operation(Stack, Top_of_stack);
+ }
+ }
+ else if (!strncmp(Otemp, "$<", 2))
+ {
+ Otemp++;
+ Otemp++;
+ delay = atoi(Otemp);
+ while (*Otemp != '>')
+ Otemp++;
+ Otemp++;
+ chars = delay * chars_per_millisecond;
+ delay = chars;
+ if ((chars - delay) > 0.0)
+ delay++;
+ if (String_table[pc__] == NULL)
+ temp = 0;
+ else
+ temp = *String_table[pc__];
+ for (; delay > 0; delay--)
+ putc(temp, stdout);
+ }
+ else
+ {
+ putchar(*Otemp);
+ Otemp++;
+ }
+ }
+ fflush(stdout);
+}
+#endif
+
+void
+wmove(window, row, column) /* move cursor to indicated position in window */
+WINDOW *window;
+int row, column;
+{
+ if ((row < window->Num_lines) && (column < window->Num_cols))
+ {
+ window->LX = column;
+ window->LY = row;
+ }
+}
+
+void
+clear_line(line, column, cols)
+struct _line *line;
+int column;
+int cols;
+{
+ int j;
+
+ if (column > line->last_char)
+ line->row[line->last_char] = ' ';
+ line->last_char = column;
+ line->row[column] = (char) NULL;
+ line->attributes[column] = (char) NULL;
+ line->changed = TRUE;
+ for (j = column + 1; j < cols; j++)
+ {
+ line->row[j] = ' ';
+ line->attributes[j] = (char) NULL;
+ }
+}
+
+void
+werase(window) /* clear the specified window */
+WINDOW *window;
+{
+ int i;
+ struct _line *tmp;
+
+ window->SCROLL_CLEAR = CLEAR;
+ window->scroll_up = window->scroll_down = 0;
+ for (i = 0, tmp = window->first_line; i < window->Num_lines; i++, tmp = tmp->next_screen)
+ clear_line(tmp, 0, window->Num_cols);
+}
+
+void
+wclrtoeol(window) /* erase from current cursor position to end of line */
+WINDOW *window;
+{
+ int column, row;
+ struct _line *tmp;
+
+ window->SCROLL_CLEAR = CHANGE;
+ column = window->LX;
+ row = window->LY;
+ for (row = 0, tmp = window->first_line; row < window->LY; row++)
+ tmp = tmp->next_screen;
+ clear_line(tmp, column, window->Num_cols);
+}
+
+void
+wrefresh(window) /* flush all previous output */
+WINDOW *window;
+{
+ wnoutrefresh(window);
+#ifdef DIAG
+{
+ struct _line *temp;
+ int value;
+ fprintf(stderr, "columns=%d, lines=%d, SC=%d, SR=%d\n",window->Num_cols, window->Num_lines, window->SC, window->SR);
+ for (value = 0, temp = window->first_line; value < window->Num_lines; value++, temp = temp->next_screen)
+ {
+ if (temp->number == -1)
+ fprintf(stderr, "line moved ");
+ if (temp->scroll)
+ fprintf(stderr, "scroll_x is set: ");
+ fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row);
+ }
+ fprintf(stderr, "+-------------------- virtual screen ----------------------------------------+\n");
+ fprintf(stderr, "columns=%d, lines=%d \n",virtual_scr->Num_cols, virtual_scr->Num_lines);
+ for (value = 0, temp = virtual_scr->first_line; value < virtual_scr->Num_lines; value++, temp = temp->next_screen)
+ {
+ if (temp->number == -1)
+ fprintf(stderr, "line moved ");
+ if (temp->scroll)
+ fprintf(stderr, "scroll_x is set: ");
+ fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row);
+ }
+ fprintf(stderr, "columns=%d, lines=%d \n",curscr->Num_cols, curscr->Num_lines);
+ for (value = 0, temp = curscr->first_line; value < curscr->Num_lines; value++, temp = temp->next_screen)
+ fprintf(stderr, "line=%s|\n", temp->row);
+}
+#endif
+ doupdate();
+ virtual_scr->SCROLL_CLEAR = FALSE;
+ virtual_scr->scroll_down = virtual_scr->scroll_up = 0;
+ fflush(stdout);
+}
+
+void
+touchwin(window)
+WINDOW *window;
+{
+ struct _line *user_line;
+ int line_counter = 0;
+
+ for (line_counter = 0, user_line = window->first_line;
+ line_counter < window->Num_lines; line_counter++)
+ {
+ user_line->changed = TRUE;
+ }
+ window->SCROLL_CLEAR = TRUE;
+}
+
+void
+wnoutrefresh(window)
+WINDOW *window;
+{
+ struct _line *user_line;
+ struct _line *virtual_line;
+ int line_counter = 0;
+ int user_col = 0;
+ int virt_col = 0;
+
+ if (window->SR >= virtual_scr->Num_lines)
+ return;
+ user_line = window->first_line;
+ virtual_line = virtual_scr->first_line;
+ virtual_scr->SCROLL_CLEAR = window->SCROLL_CLEAR;
+ virtual_scr->LX = window->LX + window->SC;
+ virtual_scr->LY = window->LY + window->SR;
+ virtual_scr->scroll_up = window->scroll_up;
+ virtual_scr->scroll_down = window->scroll_down;
+ if ((last_window_refreshed == window) && (!window->SCROLL_CLEAR))
+ return;
+ for (line_counter = 0; line_counter < window->SR; line_counter++)
+ {
+ virtual_line = virtual_line->next_screen;
+ }
+ for (line_counter = 0; (line_counter < window->Num_lines)
+ && ((line_counter + window->SR) < virtual_scr->Num_lines);
+ line_counter++)
+ {
+ if ((last_window_refreshed != window) || (user_line->changed) || ((SCROLL | CLEAR) & window->SCROLL_CLEAR))
+ {
+ for (user_col = 0, virt_col = window->SC;
+ (virt_col < virtual_scr->Num_cols)
+ && (user_col < window->Num_cols);
+ virt_col++, user_col++)
+ {
+ virtual_line->row[virt_col] = user_line->row[user_col];
+ virtual_line->attributes[virt_col] = user_line->attributes[user_col];
+ }
+ }
+ if (virtual_scr->Num_cols != window->Num_cols)
+ {
+ if (virtual_line->last_char < (user_line->last_char + window->SC))
+ {
+ if (virtual_line->row[virtual_line->last_char] == (char) NULL)
+ virtual_line->row[virtual_line->last_char] = ' ';
+ virtual_line->last_char =
+ min(virtual_scr->Num_cols,
+ (user_line->last_char + window->SC));
+ }
+ else if (virtual_line->last_char > (user_line->last_char + window->SC))
+ {
+ virtual_line->row[min(virtual_scr->Num_cols,
+ (user_line->last_char + window->SC))] = ' ';
+ }
+ }
+ else
+ virtual_line->last_char = user_line->last_char;
+ virtual_line->row[virtual_line->last_char] = (char) NULL;
+ virtual_line->changed = user_line->changed;
+ virtual_line = virtual_line->next_screen;
+ user_line = user_line->next_screen;
+ }
+ window->SCROLL_CLEAR = FALSE;
+ window->scroll_up = window->scroll_down = 0;
+ last_window_refreshed = window;
+}
+
+void
+flushinp() /* flush input */
+{
+}
+
+void
+ungetch(c) /* push a character back on input */
+int c;
+{
+ if (bufp < 100)
+ in_buff[bufp++] = c;
+}
+
+#ifdef BSD_SELECT
+int
+timed_getchar()
+{
+ struct timeval tv;
+ fd_set fds;
+ int ret_val;
+ int nfds = 1;
+ char temp;
+
+ FD_ZERO(&fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 500000; /* half a second */
+ FD_SET(0, &fds);
+ Time_Out = FALSE; /* just in case */
+
+ ret_val = select(nfds, &fds, 0, 0, &tv);
+
+ /*
+ | if ret_val is less than zero, there was no input
+ | otherwise, get a character and return it
+ */
+
+ if (ret_val <= 0)
+ {
+ Time_Out = TRUE;
+ return(-1);
+ }
+
+ return(read(0, &temp, 1)? temp : -1);
+}
+#endif
+
+int
+wgetch(window) /* get character from specified window */
+WINDOW *window;
+{
+ int in_value;
+ char temp;
+#ifndef SYS5
+ int old_arg;
+#endif /* SYS5 */
+
+#ifdef BSD_SELECT
+ if (Noblock)
+ in_value = ((bufp > 0) ? in_buff[--bufp] : timed_getchar());
+ else
+ in_value = ((bufp > 0) ? in_buff[--bufp] : read(0, &temp, 1)? temp : -1);
+#else /* BSD_SELECT */
+#ifdef SYS5
+ in_value = ((bufp > 0) ? in_buff[--bufp] :
+ (read(0, &temp, 1)> 0) ? temp : -1);
+#else /* SYS5 */
+ if (Noblock)
+ {
+ Time_Out = FALSE;
+ old_arg = fcntl(0, F_GETFL, 0);
+ in_value = fcntl(0, F_SETFL, old_arg | FNDELAY);
+ }
+ in_value = ((bufp > 0) ? in_buff[--bufp] : read(0, &temp, 1)? temp : -1);
+ if (Noblock)
+ {
+ fcntl(0, F_SETFL, old_arg);
+ if (Time_Out)
+ in_value = -1;
+ }
+#endif /* SYS5 */
+#endif /* BSD_SELECT */
+
+ if (in_value != -1)
+ {
+ in_value &= 0xff;
+ if ((Parity) && (Num_bits < 8))
+ /* strip eighth bit if parity in use */
+ in_value &= 0177;
+ }
+ else if (interrupt_flag)
+ {
+ interrupt_flag = FALSE;
+ in_value = wgetch(window);
+ }
+
+ if ((in_value == '\033') || (in_value == '\037'))/* escape character */
+ in_value = Get_key(in_value);
+ return(in_value);
+}
+
+#ifndef BSD_SELECT
+void
+Clear(arg) /* notify that time out has occurred */
+int arg;
+{
+ Time_Out = TRUE;
+#ifdef DEBUG
+fprintf(stderr, "inside Clear()\n");
+fflush(stderr);
+#endif /* DEBUG */
+}
+#endif /* BSD_SELECT */
+
+int
+Get_key(first_char) /* try to decode key sequence */
+int first_char; /* first character of sequence */
+{
+ int in_char;
+ int Count;
+ char string[128];
+ char *Gtemp;
+ int Found;
+#ifdef SYS5
+ struct termio Gterminal;
+#else
+ struct sgttyb Gterminal;
+#endif
+ struct KEY_STACK *St_point;
+#if (!defined( BSD_SELECT)) || (!defined(SYS5))
+ int value;
+#endif /* BSD_SELECT */
+
+ Count = 0;
+ Gtemp = string;
+ string[Count++] = first_char;
+ string[Count] = (char) NULL;
+ Time_Out = FALSE;
+#ifndef BSD_SELECT
+ signal(SIGALRM, Clear);
+ value = alarm(1);
+#endif /* BSD_SELECT */
+ Noblock = TRUE;
+#ifdef SYS5
+ Gterminal.c_cc[VTIME] = 0; /* timeout value */
+ Gterminal.c_lflag &= ~ICANON; /* disable canonical operation */
+ Gterminal.c_lflag &= ~ECHO; /* disable echo */
+#endif
+ Count = 1;
+ Found = FALSE;
+ while ((Count < Max_Key_len) && (!Time_Out) && (!Found))
+ {
+ in_char = wgetch(stdscr);
+#ifdef DEBUG
+fprintf(stderr, "back in GetKey()\n");
+fflush(stderr);
+#endif /* DEBUG */
+ if (in_char != -1)
+ {
+ string[Count++] = in_char;
+ string[Count] = (char) NULL;
+ St_point = KEY_TOS;
+ while ((St_point != NULL) && (!Found))
+ {
+ if (!strcmp(string, St_point->element->string))
+ Found = TRUE;
+ else
+ St_point = St_point->next;
+ }
+ }
+ }
+#ifndef BSD_SELECT
+ if (!Time_Out)
+ value = alarm(0);
+#endif /* BSD_SELECT */
+#ifdef SYS5
+/* value = ioctl(0, TCSETA, &Terminal);*/
+#else
+ value = ioctl(0, TIOCSETP, &Terminal);
+/* value = fcntl(0, F_SETFL, old_arg);*/
+#endif
+ Noblock = FALSE;
+ if (Found)
+ {
+ return(St_point->element->value);
+ }
+ else
+ {
+ while (Count > 1)
+ {
+ if ((string[--Count] != -1) &&
+ ((unsigned char) (string[Count]) != 255))
+ {
+#ifdef DIAG
+fprintf(stderr, "ungetting character %d\n", string[Count]);fflush(stdout);
+#endif
+ ungetch(string[Count]);
+ }
+ }
+ return(first_char);
+ }
+}
+
+void
+waddch(window, c) /* output the character in the specified window */
+WINDOW *window;
+int c;
+{
+ int row, column;
+ int shift; /* number of spaces to shift if a tab */
+ struct _line *tmpline;
+
+#ifdef DIAG
+/*printf("starting waddch \n");fflush(stdout);*/
+#endif
+ row = window->LY;
+ column = window->LX;
+ if (c == '\t')
+ {
+ shift = (column + 1) % 8;
+ if (shift == 0)
+ shift++;
+ else
+ shift = 9 - shift;
+ while (shift > 0)
+ {
+ shift--;
+ waddch(window, ' ');
+ }
+ }
+ else if ((column < window->Num_cols) && (row < window->Num_lines))
+ {
+ if ((c == '~') && (Booleans[hz__]))
+ c = '@';
+
+ if (( c != '\b') && (c != '\n') && (c != '\r'))
+ {
+ row = 0;
+ tmpline = window->first_line;
+ while (row < window->LY)
+ {
+ row++;
+ tmpline = tmpline->next_screen;
+ }
+ tmpline->row[column] = c;
+ tmpline->attributes[column] = window->Attrib;
+ tmpline->changed = TRUE;
+ if (column >= tmpline->last_char)
+ {
+ if (column > tmpline->last_char)
+ tmpline->row[tmpline->last_char] = ' ';
+ tmpline->row[column + 1] = (char) NULL;
+ tmpline->attributes[column + 1] = (char) NULL;
+ tmpline->last_char = column + 1;
+ }
+ }
+ if (c == '\n')
+ {
+ wclrtoeol(window);
+ window->LX = window->Num_cols;
+ }
+ else if (c == '\r')
+ window->LX = 0;
+ else if (c == '\b')
+ window->LX--;
+ else
+ window->LX++;
+ }
+ if (window->LX >= window->Num_cols)
+ {
+ window->LX = 0;
+ window->LY++;
+ if (window->LY >= window->Num_lines)
+ {
+ window->LY = window->Num_lines - 1;
+/* window->LY = row;
+ wmove(window, 0, 0);
+ wdeleteln(window);
+ wmove(window, row, 0);*/
+ }
+ }
+ window->SCROLL_CLEAR = CHANGE;
+}
+
+void
+winsertln(window) /* insert a blank line into the specified window */
+WINDOW *window;
+{
+ int row, column;
+ struct _line *tmp;
+ struct _line *tmp1;
+
+ window->scroll_down += 1;
+ window->SCROLL_CLEAR = SCROLL;
+ column = window->LX;
+ row = window->LY;
+ for (row = 0, tmp = window->first_line; (row < window->Num_lines) && (tmp->next_screen != NULL); row++)
+ tmp = tmp->next_screen;
+ if (tmp->prev_screen != NULL)
+ tmp->prev_screen->next_screen = NULL;
+ tmp1 = tmp;
+ clear_line(tmp1, 0, window->Num_cols);
+ tmp1->number = -1;
+ for (row = 0, tmp = window->first_line; (row < window->LY) && (tmp->next_screen != NULL); row++)
+ tmp = tmp->next_screen;
+ if ((window->LY == (window->Num_lines - 1)) && (window->Num_lines > 1))
+ {
+ tmp1->next_screen = tmp->next_screen;
+ tmp->next_screen = tmp1;
+ tmp->changed = TRUE;
+ tmp->next_screen->prev_screen = tmp;
+ }
+ else if (window->Num_lines > 1)
+ {
+ if (tmp->prev_screen != NULL)
+ tmp->prev_screen->next_screen = tmp1;
+ tmp1->prev_screen = tmp->prev_screen;
+ tmp->prev_screen = tmp1;
+ tmp1->next_screen = tmp;
+ tmp->changed = TRUE;
+ tmp->scroll = DOWN;
+ }
+ if (window->LY == 0)
+ window->first_line = tmp1;
+}
+
+void
+wdeleteln(window) /* delete a line in the specified window */
+WINDOW *window;
+{
+ int row, column;
+ struct _line *tmp;
+ struct _line *tmpline;
+
+ if (window->Num_lines > 1)
+ {
+ window->scroll_up += 1;
+ window->SCROLL_CLEAR = SCROLL;
+ column = window->LX;
+ row = window->LY;
+ for (row = 0, tmp = window->first_line; row < window->LY; row++)
+ tmp = tmp->next_screen;
+ if (window->LY == 0)
+ window->first_line = tmp->next_screen;
+ if (tmp->prev_screen != NULL)
+ tmp->prev_screen->next_screen = tmp->next_screen;
+ if (tmp->next_screen != NULL)
+ {
+ tmp->next_screen->changed = TRUE;
+ tmp->next_screen->scroll = UP;
+ tmp->next_screen->prev_screen = tmp->prev_screen;
+ }
+ tmpline = tmp;
+ clear_line(tmpline, 0, window->Num_cols);
+ tmpline->number = -1;
+ for (row = 0, tmp = window->first_line; tmp->next_screen != NULL; row++)
+ tmp = tmp->next_screen;
+ if (tmp != NULL)
+ {
+ tmp->next_screen = tmpline;
+ tmp->next_screen->prev_screen = tmp;
+ tmp->changed = TRUE;
+ tmp = tmp->next_screen;
+ }
+ else
+ tmp = tmpline;
+ tmp->next_screen = NULL;
+ }
+ else
+ {
+ clear_line(window->first_line, 0, window->Num_cols);
+ }
+}
+
+void
+wclrtobot(window) /* delete from current position to end of the window */
+WINDOW *window;
+{
+ int row, column;
+ struct _line *tmp;
+
+ window->SCROLL_CLEAR |= CLEAR;
+ column = window->LX;
+ row = window->LY;
+ for (row = 0, tmp = window->first_line; row < window->LY; row++)
+ tmp = tmp->next_screen;
+ clear_line(tmp, column, window->Num_cols);
+ for (row = (window->LY + 1); row < window->Num_lines; row++)
+ {
+ tmp = tmp->next_screen;
+ clear_line(tmp, 0, window->Num_cols);
+ }
+ wmove(window, row, column);
+}
+
+void
+wstandout(window) /* begin standout mode in window */
+WINDOW *window;
+{
+ if (Numbers[sg__] < 1) /* if not magic cookie glitch */
+ window->Attrib |= A_STANDOUT;
+}
+
+void
+wstandend(window) /* end standout mode in window */
+WINDOW *window;
+{
+ window->Attrib &= ~A_STANDOUT;
+}
+
+void
+waddstr(window, string) /* write 'string' in window */
+WINDOW *window;
+char *string;
+{
+ char *wstring;
+
+ for (wstring = string; *wstring != (char) NULL; wstring++)
+ waddch(window, *wstring);
+}
+
+void
+clearok(window, flag) /* erase screen and redraw at next refresh */
+WINDOW *window;
+int flag;
+{
+ Repaint_screen = TRUE;
+}
+
+void
+echo() /* turn on echoing */
+{
+ int value;
+
+#ifdef SYS5
+ Terminal.c_lflag |= ECHO; /* enable echo */
+ value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
+#else
+ Terminal.sg_flags |= ECHO; /* enable echo */
+ value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */
+#endif
+}
+
+void
+noecho() /* turn off echoing */
+{
+ int value;
+
+#ifdef SYS5
+ Terminal.c_lflag &= ~ECHO; /* disable echo */
+ value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
+#else
+ Terminal.sg_flags &= ~ECHO; /* disable echo */
+ value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */
+#endif
+}
+
+void
+raw() /* set to read characters immediately */
+{
+ int value;
+
+#ifdef SYS5
+ Intr = Terminal.c_cc[VINTR]; /* get the interrupt character */
+ Terminal.c_lflag &= ~ICANON; /* disable canonical operation */
+ Terminal.c_lflag &= ~ISIG; /* disable signal checking */
+#ifdef FLUSHO
+ Terminal.c_lflag &= ~FLUSHO;
+#endif
+#ifdef PENDIN
+ Terminal.c_lflag &= ~PENDIN;
+#endif
+#ifdef IEXTEN
+ Terminal.c_lflag &= ~IEXTEN;
+#endif
+ Terminal.c_cc[VMIN] = 1; /* minimum of one character */
+ Terminal.c_cc[VTIME] = 255; /* timeout value */
+ Terminal.c_cc[VINTR] = 0; /* eliminate interrupt */
+ value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
+#else
+ Terminal.sg_flags |= RAW; /* enable raw mode */
+ value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */
+#endif
+}
+
+void
+noraw() /* set to normal character read mode */
+{
+ int value;
+
+#ifdef SYS5
+ Terminal.c_lflag |= ICANON; /* enable canonical operation */
+ Terminal.c_lflag |= ISIG; /* enable signal checking */
+ Terminal.c_cc[VEOF] = 4; /* EOF character = 4 */
+ Terminal.c_cc[VEOL] = (char) NULL; /* EOL = 0 */
+ Terminal.c_cc[VINTR] = Intr; /* reset interrupt char */
+ value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
+#else
+ Terminal.sg_flags &= ~RAW; /* disable raw mode */
+ value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */
+/* old_arg = fcntl(0, F_GETFL, 0);
+ value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/
+#endif
+}
+
+void
+nl()
+{
+ int value;
+
+#ifdef SYS5
+ Terminal.c_iflag |= ICRNL; /* enable carriage-return to line-feed mapping */
+ value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
+#endif
+}
+
+void
+nonl()
+{
+ int value;
+
+#ifdef SYS5
+ Terminal.c_iflag &= ~ICRNL; /* disable carriage-return to line-feed mapping */
+ Terminal.c_iflag &= ~IGNCR; /* do not ignore carriage-return */
+ value = ioctl(0, TCSETA, &Terminal); /* set characteristics */
+#endif
+}
+
+void
+saveterm()
+{
+}
+
+void
+fixterm()
+{
+}
+
+void
+resetterm()
+{
+}
+
+void
+nodelay(window, flag)
+WINDOW *window;
+int flag;
+{
+}
+
+void
+idlok(window, flag)
+WINDOW *window;
+int flag;
+{
+}
+
+void
+keypad(window, flag)
+WINDOW *window;
+int flag;
+{
+ if (flag)
+ String_Out(String_table[ks__], NULL, 0);
+ else
+ String_Out(String_table[ke__], NULL, 0);
+}
+
+void
+savetty() /* save current tty stats */
+{
+ int value;
+
+#ifdef SYS5
+ value = ioctl(0, TCGETA, &Saved_tty); /* set characteristics */
+#else
+ value = ioctl(0, TIOCGETP, &Saved_tty); /* set characteristics */
+#endif
+}
+
+void
+resetty() /* restore previous tty stats */
+{
+ int value;
+
+#ifdef SYS5
+ value = ioctl(0, TCSETA, &Saved_tty); /* set characteristics */
+#else
+ value = ioctl(0, TIOCSETP, &Saved_tty); /* set characteristics */
+#endif
+}
+
+void
+endwin() /* end windows */
+{
+ keypad(stdscr, FALSE);
+ free(stdscr);
+ initialized = FALSE;
+ delwin(curscr);
+ delwin(virtual_scr);
+ delwin(stdscr);
+#ifndef SYS5
+{
+ int old_arg, value;
+/* old_arg = fcntl(0, F_GETFL, 0);
+ value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/
+}
+#endif
+}
+
+void
+delwin(window) /* delete the window structure */
+WINDOW *window;
+{
+ int i;
+
+ for (i = 1; (i < window->Num_lines) && (window->first_line->next_screen != NULL); i++)
+ {
+ window->first_line = window->first_line->next_screen;
+ free(window->first_line->prev_screen->row);
+ free(window->first_line->prev_screen->attributes);
+ free(window->first_line->prev_screen);
+ }
+ if (window == last_window_refreshed)
+ last_window_refreshed = 0;
+ if (window->first_line != NULL)
+ {
+ free(window->first_line->row);
+ free(window->first_line->attributes);
+ free(window->first_line);
+ free(window);
+ }
+}
+
+#ifndef __STDC__
+void
+wprintw(va_alist)
+va_dcl
+#else /* __STDC__ */
+void
+wprintw(WINDOW *window, const char *format, ...)
+#endif /* __STDC__ */
+{
+#ifndef __STDC__
+ WINDOW *window;
+ char *format;
+ va_list ap;
+#else
+ va_list ap;
+#endif
+ int value;
+ char *fpoint;
+ char *wtemp;
+
+#ifndef __STDC__
+ va_start(ap);
+ window = va_arg(ap, WINDOW *);
+ format = va_arg(ap, char *);
+#else /* __STDC__ */
+ va_start(ap, format);
+#endif /* __STDC__ */
+
+ fpoint = (char *) format;
+ while (*fpoint != (char) NULL)
+ {
+ if (*fpoint == '%')
+ {
+ fpoint++;
+ if (*fpoint == 'd')
+ {
+ value = va_arg(ap, int);
+ iout(window, value);
+ }
+ else if (*fpoint == 'c')
+ {
+ value = va_arg(ap, int);
+ waddch(window, value);
+ }
+ else if (*fpoint == 's')
+ {
+ wtemp = va_arg(ap, char *);
+ waddstr(window, wtemp);
+ }
+ fpoint++;
+ }
+ else if (*fpoint == '\\')
+ {
+ fpoint++;
+ if (*fpoint == 'n')
+ waddch(window, '\n');
+ else if ((*fpoint >= '0') && (*fpoint <= '9'))
+ {
+ value = 0;
+ while ((*fpoint >= '0') && (*fpoint <= '9'))
+ {
+ value = (value * 8) + (*fpoint - '0');
+ fpoint++;
+ }
+ waddch(window, value);
+ }
+ fpoint++;
+ }
+ else
+ waddch(window, *fpoint++);
+ }
+#ifdef __STDC__
+ va_end(ap);
+#endif /* __STDC__ */
+}
+
+void
+iout(window, value) /* output characters */
+WINDOW *window;
+int value;
+{
+ int i;
+
+ if ((i = value / 10) != 0)
+ iout(window, i);
+ waddch(window, ((value % 10) + '0'));
+}
+
+int
+Comp_line(line1, line2) /* compare lines */
+struct _line *line1;
+struct _line *line2;
+{
+ int count1, count2;
+ int i;
+ char *att1, *att2;
+ char *c1, *c2;
+
+ c1 = line1->row;
+ c2 = line2->row;
+ att1 = line1->attributes;
+ att2 = line2->attributes;
+ count2 = strlen(c1) + 1;
+ count1 = strlen(c2) + 1;
+ if (count1 > count2)
+ {
+ i = count2;
+ count2 = count1;
+ count1 = i;
+ }
+ if (count2 > (count1 + count1))
+ return(2);
+ i = 0;
+ while ((c1[i] != (char) NULL) && (c2[i] != (char) NULL) && (c1[i] == c2[i]) && (att1[i] == att2[i]))
+ i++;
+ count1 = i + 1;
+ if ((count1 == 1) && (count2 == 1))
+ count1 = 0; /* both lines blank */
+ else if (count2 == count1)
+ count1 = -1; /* equal */
+ else
+ count1 = count2 / count1; /* lines unequal */
+ return(count1);
+}
+
+struct _line *
+Insert_line(row, end_row, window) /* insert line into screen */
+int row;
+int end_row;
+WINDOW *window;
+{
+ int i;
+ struct _line *tmp;
+ struct _line *tmp1;
+
+ for (i = 0, tmp = curscr->first_line; i < window->SR; i++)
+ tmp = tmp->next_screen;
+ if ((end_row + window->SR) == 0)
+ curscr->first_line = curscr->first_line->next_screen;
+ top_of_win = tmp;
+ /*
+ | find bottom line to delete
+ */
+ for (i = 0, tmp = top_of_win; (tmp->next_screen != NULL) && (i < end_row); i++)
+ tmp = tmp->next_screen;
+ if (tmp->prev_screen != NULL)
+ tmp->prev_screen->next_screen = tmp->next_screen;
+ if (tmp->next_screen != NULL)
+ tmp->next_screen->prev_screen = tmp->prev_screen;
+ tmp1 = tmp;
+ /*
+ | clear deleted line
+ */
+ clear_line(tmp, 0, window->Num_cols);
+ tmp1->number = -1;
+ for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
+ tmp = tmp->next_screen;
+ top_of_win = tmp;
+ for (i = 0, tmp = top_of_win; i < row; i++)
+ tmp = tmp->next_screen;
+ if ((tmp->prev_screen != NULL) && (window->Num_lines > 0))
+ tmp->prev_screen->next_screen = tmp1;
+ tmp1->prev_screen = tmp->prev_screen;
+ tmp->prev_screen = tmp1;
+ tmp1->next_screen = tmp;
+ if ((row + window->SR) == 0)
+ curscr->first_line = tmp1;
+ if (tmp1->next_screen != NULL)
+ tmp1 = tmp1->next_screen;
+
+ if ((!String_table[cs__]) && (end_row < window->Num_lines))
+ {
+ Position(window, (window->SR + end_row), 0);
+ String_Out(String_table[dl__], NULL, 0);
+ }
+ Position(window, (window->SR + row), 0);
+ if (String_table[al__] != NULL)
+ String_Out(String_table[al__], NULL, 0);
+ else
+ String_Out(String_table[sr__], NULL, 0);
+
+ for (i = 0, top_of_win = curscr->first_line; (top_of_win->next_screen != NULL) && (i < window->SR); i++)
+ top_of_win = top_of_win->next_screen;
+ return(tmp1);
+}
+
+
+struct _line *
+Delete_line(row, end_row, window) /* delete a line on screen */
+int row;
+int end_row;
+WINDOW *window;
+{
+ int i;
+ struct _line *tmp;
+ struct _line *tmp1;
+ struct _line *tmp2;
+
+ i = 0;
+ tmp = curscr->first_line;
+ while (i < window->SR)
+ {
+ i++;
+ tmp = tmp->next_screen;
+ }
+ /*
+ | find line to delete
+ */
+ top_of_win = tmp;
+ if ((row + window->SR) == 0)
+ curscr->first_line = top_of_win->next_screen;
+ for (i = 0, tmp = top_of_win; i < row; i++)
+ tmp = tmp->next_screen;
+ if (tmp->prev_screen != NULL)
+ tmp->prev_screen->next_screen = tmp->next_screen;
+ if (tmp->next_screen != NULL)
+ tmp->next_screen->prev_screen = tmp->prev_screen;
+ tmp2 = tmp->next_screen;
+ tmp1 = tmp;
+ /*
+ | clear deleted line
+ */
+ clear_line(tmp1, 0, window->Num_cols);
+ tmp1->number = -1;
+ /*
+ | find location to insert deleted line
+ */
+ for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++)
+ tmp = tmp->next_screen;
+ top_of_win = tmp;
+ for (i = 0, tmp = top_of_win; (i < end_row) && (tmp->next_screen != NULL); i++)
+ tmp = tmp->next_screen;
+ tmp1->next_screen = tmp;
+ tmp1->prev_screen = tmp->prev_screen;
+ if (tmp1->prev_screen != NULL)
+ tmp1->prev_screen->next_screen = tmp1;
+ tmp->prev_screen = tmp1;
+
+ Position(window, (window->SR + row), 0);
+ String_Out(String_table[dl__], NULL, 0);
+ if ((!String_table[cs__]) && (end_row < window->Num_lines))
+ {
+ Position(window, (window->SR + end_row), 0);
+ String_Out(String_table[al__], NULL, 0);
+ }
+ else if ((String_table[cs__] != NULL) && (String_table[dl__] == NULL))
+ {
+ Position(window, (window->SR + end_row), 0);
+ putchar('\n');
+ }
+
+ if (row == (window->Num_lines-1))
+ tmp2 = tmp1;
+ if ((row + window->SR) == 0)
+ curscr->first_line = top_of_win = tmp2;
+ return(tmp2);
+}
+
+void
+CLEAR_TO_EOL(window, row, column)
+WINDOW *window;
+int row, column;
+{
+ int x, y;
+ struct _line *tmp1;
+
+ for (y = 0, tmp1 = curscr->first_line; (y < (window->SR+row)) && (tmp1->next_screen != NULL); y++)
+ tmp1 = tmp1->next_screen;
+ for (x = column; x<window->Num_cols; x++)
+ {
+ tmp1->row[x] = ' ';
+ tmp1->attributes[x] = (char) NULL;
+ }
+ tmp1->row[column] = (char) NULL;
+ tmp1->last_char = column;
+ if (column < COLS)
+ {
+ if (STAND)
+ {
+ STAND = FALSE;
+ Position(window, row, column);
+ attribute_off();
+ }
+ if (String_table[ce__] != NULL)
+ String_Out(String_table[ce__], NULL, 0);
+ else
+ {
+ for (x = column; x < window->Num_cols; x++)
+ putchar(' ');
+ Curr_x = x;
+ }
+ }
+}
+
+int
+check_delete(window, line, offset, pointer_new, pointer_old)
+WINDOW *window;
+int line, offset;
+struct _line *pointer_new, *pointer_old;
+{
+ int end_old;
+ int end_new;
+ int k;
+ int changed;
+ char *old_lin;
+ char *new_lin;
+ char *old_att;
+ char *new_att;
+
+ changed = FALSE;
+ new_lin = pointer_new->row;
+ new_att = pointer_new->attributes;
+ old_lin = pointer_old->row;
+ old_att = pointer_old->attributes;
+ end_old = end_new = offset;
+ while (((new_lin[end_new] != old_lin[end_old]) || (new_att[end_new] != old_att[end_old])) && (old_lin[end_old] != (char) NULL) && (new_lin[end_old] != (char) NULL))
+ end_old++;
+ if (old_lin[end_old] != (char) NULL)
+ {
+ k = 0;
+ while ((old_lin[end_old+k] == new_lin[end_new+k]) && (new_att[end_new+k] == old_att[end_old+k]) && (new_lin[end_new+k] != (char) NULL) && (old_lin[end_old+k] != (char) NULL) && (k < 10))
+ k++;
+ if ((k > 8) || ((new_lin[end_new+k] == (char) NULL) && (k != 0)))
+ {
+ if (new_lin[end_new+k] == (char) NULL)
+ {
+ Position(window, line, (end_new+k));
+ CLEAR_TO_EOL(window, line, (end_new+k));
+ }
+ Position(window, line, offset);
+ for (k = offset; k < end_old; k++)
+ Char_del(old_lin, old_att, offset, window->Num_cols);
+ while ((old_lin[offset] != (char) NULL) && (offset < COLS))
+ offset++;
+ pointer_old->last_char = offset;
+ changed = TRUE;
+ }
+ }
+ return(changed);
+}
+
+int
+check_insert(window, line, offset, pointer_new, pointer_old)
+WINDOW *window;
+int line, offset;
+struct _line *pointer_new, *pointer_old;
+{
+ int changed;
+ int end_old, end_new;
+ int k;
+ int same = FALSE;
+ int old_off;
+ int insert;
+ char *old_lin;
+ char *new_lin;
+ char *old_att;
+ char *new_att;
+
+ changed = FALSE;
+ new_lin = pointer_new->row;
+ new_att = pointer_new->attributes;
+ old_lin = pointer_old->row;
+ old_att = pointer_old->attributes;
+ end_old = end_new = offset;
+ while (((new_lin[end_new] != old_lin[end_old]) || (new_att[end_new] != old_att[end_old])) && (new_lin[end_new] != (char) NULL) && (old_lin[end_new] != (char) NULL))
+ end_new++;
+ if (new_lin[end_new] != (char) NULL)
+ {
+ k = 0;
+ while ((old_lin[end_old+k] == new_lin[end_new+k]) && (old_att[end_old+k] == new_att[end_new+k]) && (new_lin[end_new+k] != (char) NULL) && (old_lin[end_old+k] != (char) NULL) && (k < 10))
+ k++;
+ /*
+ | check for commonality between rest of lines (are the old
+ | and new lines the same, except for a chunk in the middle?)
+ | if the rest of the lines are common, do not insert text
+ */
+ old_off = end_new;
+ while ((old_lin[old_off] != (char) NULL) && (new_lin[old_off] != (char) NULL) && (old_lin[old_off] == new_lin[old_off]) && (old_att[old_off] == new_att[old_off]))
+ old_off++;
+ if ((old_lin[old_off] == new_lin[old_off]) && (old_att[old_off] == new_att[old_off]))
+ same = TRUE;
+ if ((!same) && ((k > 8) || ((new_lin[end_new+k] == (char) NULL) && (k != 0))))
+ {
+ Position(window, line, offset);
+ insert = FALSE;
+ if (String_table[ic__] == NULL)
+ {
+ String_Out(String_table[im__], NULL, 0);
+ insert = TRUE;
+ }
+ for (k = offset; k < end_new; k++)
+ {
+ if (!insert)
+ String_Out(String_table[ic__], NULL, 0);
+ Char_ins(old_lin, old_att, new_lin[k], new_att[k], k, window->Num_cols);
+ }
+ if (insert)
+ String_Out(String_table[ei__], NULL, 0);
+ while ((old_lin[offset] != (char) NULL) && (offset < COLS))
+ offset++;
+ pointer_old->last_char = offset;
+ changed = TRUE;
+ }
+ }
+ return(changed);
+}
+
+void
+doupdate()
+{
+ WINDOW *window;
+ int similar;
+ int diff;
+ int begin_old, begin_new;
+ int end_old, end_new;
+ int count1, j;
+ int from_top, tmp_ft, offset;
+ int changed;
+ int first_time;
+ int first_same;
+ int last_same;
+ int list[10];
+
+ struct _line *curr;
+ struct _line *virt;
+ struct _line *old;
+
+ struct _line *new;
+
+ char *cur_lin;
+ char *vrt_lin;
+ char *cur_att;
+ char *vrt_att;
+ char *att1, *att2;
+ char *c1, *c2;
+
+ window = virtual_scr;
+
+ if (Repaint_screen)
+ {
+ if (String_table[cl__])
+ String_Out(String_table[cl__], NULL, 0);
+ else
+ {
+ from_top = 0;
+ while (from_top < LINES)
+ {
+ Position(curscr, from_top, 0);
+ if (String_table[ce__] != NULL)
+ String_Out(String_table[ce__], NULL, 0);
+ else
+ {
+ for (j = 0; j < window->Num_cols; j++)
+ putchar(' ');
+ }
+ from_top++;
+ }
+ }
+ for (from_top = 0, curr = curscr->first_line; from_top < curscr->Num_lines; from_top++, curr = curr->next_screen)
+ {
+ Position(curscr, from_top, 0);
+ for (j = 0; (curr->row[j] != (char) NULL) && (j < curscr->Num_cols); j++)
+ {
+ Char_out(curr->row[j], curr->attributes[j], curr->row, curr->attributes, j);
+ }
+ if (STAND)
+ {
+ STAND = FALSE;
+ Position(curscr, from_top, j);
+ attribute_off();
+ }
+ }
+ Repaint_screen = FALSE;
+ }
+
+ similar = 0;
+ diff = FALSE;
+ top_of_win = curscr->first_line;
+
+ for (from_top = 0, curr = top_of_win, virt = window->first_line;
+ from_top < window->Num_lines; from_top++)
+ {
+ virtual_lines[from_top] = TRUE;
+ if ((similar = Comp_line(curr, virt)) > 0)
+ {
+ virtual_lines[from_top] = FALSE;
+ diff = TRUE;
+ }
+ curr = curr->next_screen;
+ virt = virt->next_screen;
+ }
+
+ from_top = 0;
+ virt = window->first_line;
+ curr = top_of_win;
+ similar = 0;
+ /*
+ | if the window has lines that are different
+ */
+ if (diff)
+ {
+ last_same = -1;
+ changed = FALSE;
+ for (first_same = window->Num_lines;
+ (first_same > from_top) && (virtual_lines[first_same - 1]);
+ first_same--)
+ ;
+ count1 = first_same - 1;
+ for (last_same = 0;
+ (last_same < window->Num_lines) && (virtual_lines[last_same]== FALSE);
+ last_same++)
+ ;
+ while ((from_top < first_same) && nc_scrolling_ability)
+ /* check entire lines for diffs */
+ {
+
+
+ if (from_top >= last_same)
+ {
+ for (last_same = from_top;
+ (last_same < window->Num_lines) &&
+ (virtual_lines[last_same] == FALSE);
+ last_same++)
+ ;
+ }
+ if (!virtual_lines[from_top])
+ {
+ diff = TRUE;
+ /*
+ | check for lines deleted (scroll up)
+ */
+ for (tmp_ft = from_top+1, old = curr->next_screen;
+ ((window->scroll_up) && (diff) &&
+ (tmp_ft < last_same) &&
+ (!virtual_lines[tmp_ft]));
+ tmp_ft++)
+ {
+ if ((Comp_line(old, virt) == -1) && (!virtual_lines[from_top]))
+ {
+ if (String_table[cs__]) /* scrolling region */
+ {
+ list[1] = from_top;
+ list[0] = min((last_same - 1), (window->Num_lines - 1));
+ String_Out(String_table[cs__], list, 2);
+ Curr_y = Curr_x = -1;
+ }
+
+ for (offset = (tmp_ft - from_top); (offset > 0); offset--)
+ {
+ old = Delete_line(from_top, min((last_same - 1), (window->Num_lines - 1)), window);
+ diff = FALSE;
+ }
+
+ if (String_table[cs__]) /* scrolling region */
+ {
+ list[1] = 0;
+ list[0] = LINES;
+ String_Out(String_table[cs__], list, 2);
+ Curr_y = Curr_x = -1;
+ }
+
+ top_of_win = curscr->first_line;
+ curr = top_of_win;
+ for (offset = 0; offset < from_top; offset++)
+ curr = curr->next_screen;
+ for (offset = from_top, old=curr, new=virt;
+ offset < window->Num_lines;
+ old=old->next_screen, new=new->next_screen,
+ offset++)
+ {
+ similar = Comp_line(old, new);
+ virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
+ }
+ }
+ else
+ old = old->next_screen;
+ }
+ /*
+ | check for lines inserted (scroll down)
+ */
+ for (tmp_ft = from_top-1, old = curr->prev_screen;
+ ((window->scroll_down) && (tmp_ft >= 0) &&
+ (diff) &&
+ (!virtual_lines[tmp_ft]));
+ tmp_ft--)
+ {
+ if (Comp_line(old, virt) == -1)
+ {
+ if (String_table[cs__]) /* scrolling region */
+ {
+ list[1] = tmp_ft;
+ list[0] = min((last_same - 1), (window->Num_lines - 1));
+ String_Out(String_table[cs__], list, 2);
+ Curr_y = Curr_x = -1;
+ }
+
+ for (offset = (from_top - tmp_ft); (offset > 0); offset--)
+ {
+ old = Insert_line(tmp_ft, min((last_same - 1), (window->Num_lines -1)), window);
+ diff = FALSE;
+ }
+
+ if (String_table[cs__]) /* scrolling region */
+ {
+ list[1] = 0;
+ list[0] = LINES;
+ String_Out(String_table[cs__], list, 2);
+ Curr_y = Curr_x = -1;
+ }
+
+ top_of_win = curscr->first_line;
+ curr = top_of_win;
+ for (offset = 0; offset < from_top; offset++)
+ curr = curr->next_screen;
+ for (offset = from_top, old=curr, new=virt;
+ offset < window->Num_lines;
+ old=old->next_screen, new=new->next_screen,
+ offset++)
+ {
+ similar = Comp_line(old, new);
+ virtual_lines[offset] = (similar > 0 ? FALSE : TRUE);
+ }
+ }
+ else
+ old = old->prev_screen;
+ }
+ }
+ from_top++;
+ curr = curr->next_screen;
+ virt = virt->next_screen;
+ }
+ }
+
+ for (from_top = 0, curr = curscr->first_line; from_top < window->SR; from_top++)
+ curr = curr->next_screen;
+ top_of_win = curr;
+ for (from_top = 0, curr = top_of_win, virt = window->first_line; from_top < window->Num_lines; from_top++, curr = curr->next_screen, virt = virt->next_screen)
+ {
+ if (((String_table[ic__]) || (String_table[im__])) && (String_table[dc__]) && (curr->row[0] != (char) NULL))
+ {
+ j = 0;
+ first_time = TRUE;
+ vrt_lin = virt->row;
+ vrt_att = virt->attributes;
+ cur_lin = curr->row;
+ cur_att = curr->attributes;
+ while ((vrt_lin[j] != (char) NULL) && (j < window->Num_cols))
+ {
+ if ((STAND) && (Booleans[xs__]))
+ {
+ while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != (char) NULL) && (vrt_att[j]))
+ j++;
+ if ((STAND) && (!vrt_att[j]))
+ {
+ STAND = FALSE;
+ Position(window, from_top, j);
+ attribute_off();
+ attribute_off();
+ }
+ }
+ else
+ {
+ while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != (char) NULL))
+ j++;
+ }
+ if ((vrt_att[j] != cur_att[j]) && (cur_att[j]) && (Booleans[xs__]))
+ {
+ Position(window, from_top, j);
+/* CLEAR_TO_EOL(window, from_top, j);*/
+ attribute_off();
+ attribute_off();
+ }
+ if (vrt_lin[j] != (char) NULL)
+ {
+ begin_new = j;
+ begin_old = j;
+ end_old = j;
+ end_new = j;
+ if ((first_time) && (virt->changed))
+ {
+ if (curr->last_char <= virt->last_char)
+ changed = check_insert(window, from_top, j, virt, curr);
+ }
+ changed = check_delete(window, from_top, j, virt, curr);
+ first_time = FALSE;
+ virt->changed = FALSE;
+ if (!changed)
+ changed = check_insert(window, from_top, j, virt, curr);
+ if (((!changed) || (cur_lin[j] != vrt_lin[j]) || (cur_att[j] != vrt_att[j])) && (j < window->Num_cols))
+ {
+ if ((vrt_lin[j] == ' ') && (cur_lin[j] == (char) NULL) && (vrt_att[j] == cur_att[j]))
+ cur_lin[j] = ' ';
+ else
+ {
+ Position(window, from_top, j);
+ Char_out(vrt_lin[j], vrt_att[j], cur_lin, cur_att, j);
+ }
+ }
+ if ((vrt_lin[j] != (char) NULL))
+ j++;
+ }
+ if ((STAND) && (!vrt_att[j]))
+ {
+ STAND = FALSE;
+ Position(window, from_top, j);
+ attribute_off();
+ }
+ }
+ if ((vrt_lin[j] == (char) NULL) && (cur_lin[j] != (char) NULL))
+ {
+ Position(window, from_top, j);
+ CLEAR_TO_EOL(window, from_top, j);
+ }
+ }
+ else /*if ((similar != -1) && (similar != 0))*/
+ {
+ j = 0;
+ c1 = curr->row;
+ att1 = curr->attributes;
+ c2 = virt->row;
+ att2 = virt->attributes;
+ while ((j < window->Num_cols) && (c2[j] != (char) NULL))
+ {
+ while ((c1[j] == c2[j]) && (att1[j] == att2[j]) && (j < window->Num_cols) && (c2[j] != (char) NULL))
+ j++;
+ begin_old = j;
+ begin_new = j;
+ if ((j < window->Num_cols) && (c2[j] != (char) NULL))
+ {
+ Position(window, from_top, begin_old);
+ CLEAR_TO_EOL(window, from_top, j);
+ Position(window, from_top, begin_old);
+ for (j = begin_old; (c2[j] != (char) NULL) && (j < window->Num_cols); j++)
+ Char_out(c2[j], att2[j], c1, att1, j);
+ }
+ }
+ if ((c2[j] == (char) NULL) && (c1[j] != (char) NULL))
+ {
+ Position(window, from_top, j);
+ CLEAR_TO_EOL(window, from_top, j);
+ }
+ }
+ if (STAND)
+ {
+ STAND = FALSE;
+ Position(window, from_top, j);
+ attribute_off();
+ }
+ virt->number = from_top;
+ }
+ Position(window, window->LY, window->LX);
+}
+
+void
+Position(window, row, col) /* position the cursor for output on the screen */
+WINDOW *window;
+int row;
+int col;
+{
+ int list[10];
+ int place;
+
+ int pos_row;
+ int pos_column;
+
+ pos_row = row + window->SR;
+ pos_column = col + window->SC;
+ if ((pos_row != Curr_y) || (pos_column != Curr_x))
+ {
+ if (String_table[cm__] != NULL) /* && (row < window->Num_lines) && (column < window->Num_cols))*/
+ {
+ place = 0;
+ list[place++] = pos_column;
+ list[place++] = pos_row;
+ String_Out(String_table[cm__], list, place);
+ if ((STAND) && (!Booleans[ms__]))
+ attribute_on();
+ }
+ Curr_x = pos_column;
+ Curr_y = pos_row;
+ }
+}
+
+void
+Char_del(line, attrib, offset, maxlen) /* delete chars from line */
+char *line;
+char *attrib;
+int offset;
+int maxlen;
+{
+ int one, two;
+
+ for (one = offset, two = offset+1; (line[one] != (char) NULL) && (one < maxlen); one++, two++)
+ {
+ line[one] = line[two];
+ attrib[one] = attrib[two];
+ }
+ String_Out(String_table[dc__], NULL, 0);
+}
+
+void
+Char_ins(line, attrib, newc, newatt, offset, maxlen) /* insert chars in line */
+char *line;
+char *attrib;
+char newc;
+char newatt;
+int offset;
+int maxlen;
+{
+ int one, two;
+
+ one = 0;
+ while ((line[one] != (char) NULL) && (one < (maxlen - 2)))
+ one++;
+ for (two = one + 1; (two > offset); one--, two--)
+ {
+ line[two] = line[one];
+ attrib[two] = attrib[one];
+ }
+ line[offset] = newc;
+ attrib[offset] = newatt;
+ Char_out(newc, newatt, line, attrib, offset);
+}
+
+void
+attribute_on()
+{
+ if (String_table[sa__])
+ {
+ attributes_set[0] = 1;
+ String_Out(String_table[sa__], attributes_set, 1);
+ }
+ else if (String_table[so__])
+ String_Out(String_table[so__], NULL, 0);
+}
+
+void
+attribute_off()
+{
+ if (String_table[me__])
+ String_Out(String_table[me__], NULL, 0);
+ else if (String_table[sa__])
+ {
+ attributes_set[0] = 0;
+ String_Out(String_table[sa__], attributes_set, 1);
+ }
+ else if (String_table[se__])
+ String_Out(String_table[se__], NULL, 0);
+}
+
+void
+Char_out(newc, newatt, line, attrib, offset) /* output character with proper attribute */
+char newc;
+char newatt;
+char *line;
+char *attrib;
+int offset;
+{
+
+
+ if ((newatt) && (!STAND))
+ {
+ STAND = TRUE;
+ attribute_on();
+ }
+ else if ((STAND) && (!newatt))
+ {
+ STAND = FALSE;
+ attribute_off();
+ }
+
+ if ((newatt) && (STAND) && (Booleans[xs__]))
+ {
+ attribute_on();
+ }
+
+ if (!((Curr_y >= (LINES - 1)) && (Curr_x >= (COLS - 1))))
+ {
+ putchar(newc);
+ line[offset] = newc;
+ attrib[offset] = newatt;
+ }
+ Curr_x++;
+}
+
diff --git a/usr.bin/ee/doc/new_curse.h b/usr.bin/ee/doc/new_curse.h
new file mode 100644
index 0000000000000..f69ee5910bda0
--- /dev/null
+++ b/usr.bin/ee/doc/new_curse.h
@@ -0,0 +1,255 @@
+/*
+ | new_curse.h
+ |
+ | A subset of curses developed for use with ae.
+ |
+ | written by Hugh Mahon
+ |
+ | THIS MATERIAL IS PROVIDED "AS IS". THERE ARE
+ | NO WARRANTIES OF ANY KIND WITH REGARD TO THIS
+ | MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE
+ | IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ | FITNESS FOR A PARTICULAR PURPOSE. Neither
+ | Hewlett-Packard nor Hugh Mahon shall be liable
+ | for errors contained herein, nor for
+ | incidental or consequential damages in
+ | connection with the furnishing, performance or
+ | use of this material. Neither Hewlett-Packard
+ | nor Hugh Mahon assumes any responsibility for
+ | the use or reliability of this software or
+ | documentation. This software and
+ | documentation is totally UNSUPPORTED. There
+ | is no support contract available. Hewlett-
+ | Packard has done NO Quality Assurance on ANY
+ | of the program or documentation. You may find
+ | the quality of the materials inferior to
+ | supported materials.
+ |
+ | This software is not a product of Hewlett-Packard, Co., or any
+ | other company. No support is implied or offered with this software.
+ | You've got the source, and you're on your own.
+ |
+ | This software may be distributed under the terms of Larry Wall's
+ | Artistic license, a copy of which is included in this distribution.
+ |
+ | This notice must be included with this software and any derivatives.
+ |
+ | Copyright (c) 1986, 1987, 1988, 1991, 1995 Hugh Mahon
+ | All are rights reserved.
+ |
+ */
+
+#include <stdio.h>
+
+#ifdef SYS5
+#include <termio.h>
+#else
+#include <sgtty.h>
+#include <fcntl.h>
+#endif
+
+#define KEY_BREAK 0401
+#define KEY_DOWN 0402
+#define KEY_UP 0403
+#define KEY_LEFT 0404
+#define KEY_RIGHT 0405
+#define KEY_HOME 0406
+#define KEY_BACKSPACE 0407
+#define KEY_F0 0410
+#define KEY_F(n) (KEY_F0+(n))
+#define KEY_DL 0510
+#define KEY_IL 0511
+#define KEY_DC 0512
+#define KEY_IC 0513
+#define KEY_EIC 0514
+#define KEY_CLEAR 0515
+#define KEY_EOS 0516
+#define KEY_EOL 0517
+#define KEY_SF 0520
+#define KEY_SR 0521
+#define KEY_NPAGE 0522
+#define KEY_PPAGE 0523
+#define KEY_STAB 0524
+#define KEY_CTAB 0525
+#define KEY_CATAB 0526
+#define KEY_ENTER 0527
+#define KEY_SRESET 0530
+#define KEY_RESET 0531
+#define KEY_PRINT 0532
+#define KEY_LL 0533
+#define KEY_A1 0534
+#define KEY_A3 0535
+#define KEY_B2 0536
+#define KEY_C1 0537
+#define KEY_C3 0540
+#define KEY_BTAB 0541
+#define KEY_BEG 0542
+#define KEY_CANCEL 0543
+#define KEY_CLOSE 0544
+#define KEY_COMMAND 0545
+#define KEY_COPY 0546
+#define KEY_CREATE 0547
+#define KEY_END 0550
+#define KEY_EXIT 0551
+#define KEY_FIND 0552
+#define KEY_HELP 0553
+#define KEY_MARK 0554
+#define KEY_MESSAGE 0555
+#define KEY_MOVE 0556
+#define KEY_NEXT 0557
+#define KEY_OPEN 0560
+#define KEY_OPTIONS 0561
+#define KEY_PREVIOUS 0562
+#define KEY_REDO 0563
+#define KEY_REFERENCE 0564
+#define KEY_REFRESH 0565
+#define KEY_REPLACE 0566
+#define KEY_RESTART 0567
+#define KEY_RESUME 0570
+#define KEY_SAVE 0571
+#define KEY_SBEG 0572
+#define KEY_SCANCEL 0573
+#define KEY_SCOMMAND 0574
+#define KEY_SCOPY 0575
+#define KEY_SCREATE 0576
+#define KEY_SDC 0577
+#define KEY_SDL 0600
+#define KEY_SELECT 0601
+#define KEY_SEND 0602
+#define KEY_SEOL 0603
+#define KEY_SEXIT 0604
+#define KEY_SFIND 0605
+#define KEY_SHELP 0606
+#define KEY_SHOME 0607
+#define KEY_SIC 0610
+#define KEY_SLEFT 0611
+#define KEY_SMESSAGE 0612
+#define KEY_SMOVE 0613
+#define KEY_SNEXT 0614
+#define KEY_SOPTIONS 0615
+#define KEY_SPREVIOUS 0616
+#define KEY_SPRINT 0617
+#define KEY_SREDO 0620
+#define KEY_SREPLACE 0621
+#define KEY_SRIGHT 0622
+#define KEY_SRSUME 0623
+#define KEY_SSAVE 0624
+#define KEY_SSUSPEND 0625
+#define KEY_SUNDO 0626
+#define KEY_SUSPEND 0627
+#define KEY_UNDO 0630
+
+#define TRUE 1
+#define FALSE 0
+
+#define A_STANDOUT 0001 /* standout mode */
+#define SCROLL 1 /* text has been scrolled */
+#define CLEAR 2 /* window has been cleared */
+#define CHANGE 3 /* window has been changed */
+#define UP 1 /* direction of scroll */
+#define DOWN 2
+
+struct _line {
+ struct _line *next_screen;
+ struct _line *prev_screen;
+ char *row;
+ char *attributes;
+ int last_char;
+ int changed;
+ int scroll;
+ int number;
+ };
+
+struct _line *top_of_win;
+
+typedef struct WIND {
+ int SR; /* starting row */
+ int SC; /* starting column */
+ int LC; /* last column */
+ int LX; /* last cursor column position */
+ int LY; /* last cursor row position */
+ int Attrib; /* attributes active in window */
+ int Num_lines; /* number of lines */
+ int Num_cols; /* number of columns */
+ int scroll_up; /* number of lines moved */
+ int scroll_down;
+ int SCROLL_CLEAR; /* indicates that window has been scrolled or cleared */
+ struct _line *first_line;
+ } WINDOW;
+
+extern WINDOW *curscr;
+extern WINDOW *stdscr;
+
+extern int LINES, COLS;
+
+#if __STDC__ || defined(__cplusplus)
+#define P_(s) s
+#else
+#define P_(s) ()
+#endif
+
+extern void copy_window P_((WINDOW *origin, WINDOW *destination));
+extern void reinitscr P_((int));
+extern void initscr P_((void));
+extern int Get_int P_((void));
+extern int INFO_PARSE P_((void));
+extern int AtoI P_((void));
+extern void Key_Get P_((void));
+extern struct _line *Screenalloc P_((int columns));
+extern WINDOW *newwin P_((int lines, int cols, int start_l, int start_c));
+extern int Operation P_((int Temp_Stack[], int place));
+extern void Info_Out P_((char *string, int p_list[], int place));
+extern void wmove P_((WINDOW *window, int row, int column));
+extern void clear_line P_((struct _line *line, int column, int cols));
+extern void werase P_((WINDOW *window));
+extern void wclrtoeol P_((WINDOW *window));
+extern void wrefresh P_((WINDOW *window));
+extern void touchwin P_((WINDOW *window));
+extern void wnoutrefresh P_((WINDOW *window));
+extern void flushinp P_((void));
+extern void ungetch P_((int c));
+extern int wgetch P_((WINDOW *window));
+extern void Clear P_((int));
+extern int Get_key P_((int first_char));
+extern void waddch P_((WINDOW *window, int c));
+extern void winsertln P_((WINDOW *window));
+extern void wdeleteln P_((WINDOW *window));
+extern void wclrtobot P_((WINDOW *window));
+extern void wstandout P_((WINDOW *window));
+extern void wstandend P_((WINDOW *window));
+extern void waddstr P_((WINDOW *window, char *string));
+extern void clearok P_((WINDOW *window, int flag));
+extern void echo P_((void));
+extern void noecho P_((void));
+extern void raw P_((void));
+extern void noraw P_((void));
+extern void nl P_((void));
+extern void nonl P_((void));
+extern void saveterm P_((void));
+extern void fixterm P_((void));
+extern void resetterm P_((void));
+extern void nodelay P_((WINDOW *window, int flag));
+extern void idlok P_((WINDOW *window, int flag));
+extern void keypad P_((WINDOW *window, int flag));
+extern void savetty P_((void));
+extern void resetty P_((void));
+extern void endwin P_((void));
+extern void delwin P_((WINDOW *window));
+extern void wprintw P_((WINDOW *window, __const char* format, ...));
+extern void iout P_((WINDOW *window, int value));
+extern int Comp_line P_((struct _line *line1, struct _line *line2));
+extern struct _line *Insert_line P_((int row, int end_row, WINDOW *window));
+extern struct _line *Delete_line P_((int row, int end_row, WINDOW *window));
+extern void CLEAR_TO_EOL P_((WINDOW *window, int row, int column));
+extern int check_delete P_((WINDOW *window, int line, int offset, struct _line *pointer_new, struct _line *pointer_old));
+extern int check_insert P_((WINDOW *window, int line, int offset, struct _line *pointer_new, struct _line *pointer_old));
+extern void doupdate P_((void));
+extern void Position P_((WINDOW *window, int row, int col));
+extern void Char_del P_((char *line, char *attrib, int offset, int maxlen));
+extern void Char_ins P_((char *line, char *attrib, int newc, int newatt, int offset, int maxlen));
+extern void attribute_on P_((void));
+extern void attribute_off P_((void));
+extern void Char_out P_((int newc, int newatt, char *line, char *attrib, int offset));
+
+#undef P_
+
diff --git a/usr.bin/ee/ee.c b/usr.bin/ee/ee.c
new file mode 100644
index 0000000000000..876a58c79399e
--- /dev/null
+++ b/usr.bin/ee/ee.c
@@ -0,0 +1,4795 @@
+/*
+ | ee (easy editor)
+ |
+ | An easy to use, simple screen oriented editor.
+ |
+ | written by Hugh Mahon
+ |
+ | THIS MATERIAL IS PROVIDED "AS IS". THERE ARE
+ | NO WARRANTIES OF ANY KIND WITH REGARD TO THIS
+ | MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE
+ | IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ | FITNESS FOR A PARTICULAR PURPOSE. Neither
+ | Hewlett-Packard nor Hugh Mahon shall be liable
+ | for errors contained herein, nor for
+ | incidental or consequential damages in
+ | connection with the furnishing, performance or
+ | use of this material. Neither Hewlett-Packard
+ | nor Hugh Mahon assumes any responsibility for
+ | the use or reliability of this software or
+ | documentation. This software and
+ | documentation is totally UNSUPPORTED. There
+ | is no support contract available. Hewlett-
+ | Packard has done NO Quality Assurance on ANY
+ | of the program or documentation. You may find
+ | the quality of the materials inferior to
+ | supported materials.
+ |
+ | This software is not a product of Hewlett-Packard, Co., or any
+ | other company. No support is implied or offered with this software.
+ | You've got the source, and you're on your own.
+ |
+ | This software may be distributed under the terms of Larry Wall's
+ | Artistic license, a copy of which is included in this distribution.
+ |
+ | This notice must be included with this software and any derivatives.
+ |
+ | This editor was purposely developed to be simple, both in
+ | interface and implementation. This editor was developed to
+ | address a specific audience: the user who is new to computers
+ | (especially UNIX).
+ |
+ | ee is not aimed at technical users; for that reason more
+ | complex features were intentionally left out. In addition,
+ | ee is intended to be compiled by people with little computer
+ | experience, which means that it needs to be small, relatively
+ | simple in implementation, and portable.
+ |
+ | This software and documentation contains
+ | proprietary information which is protected by
+ | copyright. All rights are reserved.
+ |
+ | $Header: /home/ncvs/src/usr.bin/ee/ee.c,v 1.2 1995/08/30 17:11:54 ache Exp $
+ |
+ */
+
+char *ee_copyright_message =
+"Copyright (c) 1986, 1990, 1991, 1992, 1993, 1994, 1995 Hugh Mahon ";
+
+char *ee_long_notice[] = {
+ "This software and documentation contains",
+ "proprietary information which is protected by",
+ "copyright. All rights are reserved."
+ };
+
+char *version = "@(#) ee, version 1.2.4 $Revision: 1.2 $";
+
+#ifdef NCURSE
+#include "new_curse.h"
+#else
+#ifdef HAS_NCURSES
+#include <ncurses.h>
+#else
+#include <curses.h>
+#endif
+#endif
+
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <pwd.h>
+
+#ifdef HAS_SYS_WAIT
+#include <sys/wait.h>
+#endif
+
+#ifdef HAS_STDLIB
+#include <stdlib.h>
+#endif
+
+#ifdef HAS_STDARG
+#include <stdarg.h>
+#endif
+
+#ifdef HAS_UNISTD
+#include <unistd.h>
+#endif
+
+#ifdef HAS_CTYPE
+#include <ctype.h>
+#endif
+
+
+#ifndef NO_CATGETS
+#include <locale.h>
+#include <nl_types.h>
+
+nl_catd catalog;
+#else
+#define catgetlocal(a, b) (b)
+#endif /* NO_CATGETS */
+
+#ifndef SIGCHLD
+#define SIGCHLD SIGCLD
+#endif
+
+#define TAB 9
+#define max(a, b) (a > b ? a : b)
+#define min(a, b) (a < b ? a : b)
+
+/*
+ | defines for type of data to show in info window
+ */
+
+#define CONTROL_KEYS 1
+#define COMMANDS 2
+
+struct text {
+ char *line; /* line of characters */
+ int line_number; /* line number */
+ int line_length; /* actual number of characters in the line */
+ int max_length; /* maximum number of characters the line handles */
+ struct text *next_line; /* next line of text */
+ struct text *prev_line; /* previous line of text */
+ };
+
+struct text *first_line; /* first line of current buffer */
+struct text *dlt_line; /* structure for info on deleted line */
+struct text *curr_line; /* current line cursor is on */
+struct text *tmp_line; /* temporary line pointer */
+struct text *srch_line; /* temporary pointer for search routine */
+
+struct files { /* structure to store names of files to be edited*/
+ char *name; /* name of file */
+ struct files *next_name;
+ };
+
+struct files *top_of_stack = NULL;
+
+int d_wrd_len; /* length of deleted word */
+int position; /* offset in bytes from begin of line */
+int scr_pos; /* horizontal position */
+int scr_vert; /* vertical position on screen */
+int scr_horz; /* horizontal position on screen */
+int tmp_vert, tmp_horz;
+int input_file; /* indicate to read input file */
+int recv_file; /* indicate reading a file */
+int edit; /* continue executing while true */
+int gold; /* 'gold' function key pressed */
+int fildes; /* file descriptor */
+int case_sen; /* case sensitive search flag */
+int last_line; /* last line for text display */
+int last_col; /* last column for text display */
+int horiz_offset = 0; /* offset from left edge of text */
+int clear_com_win; /* flag to indicate com_win needs clearing */
+int text_changes = FALSE; /* indicate changes have been made to text */
+int get_fd; /* file descriptor for reading a file */
+int info_window = TRUE; /* flag to indicate if help window visible */
+int info_type = CONTROL_KEYS; /* flag to indicate type of info to display */
+int expand_tabs = TRUE; /* flag for expanding tabs */
+int right_margin = 0; /* the right margin */
+int observ_margins = TRUE; /* flag for whether margins are observed */
+int shell_fork;
+int temp_stdin; /* temporary storage for stdin */
+int temp_stdout; /* temp storage for stdout descriptor */
+int temp_stderr; /* temp storage for stderr descriptor */
+int pipe_out[2]; /* pipe file desc for output */
+int pipe_in[2]; /* pipe file descriptors for input */
+int out_pipe; /* flag that info is piped out */
+int in_pipe; /* flag that info is piped in */
+int formatted = FALSE; /* flag indicating paragraph formatted */
+int auto_format = FALSE; /* flag for auto_format mode */
+int restricted = FALSE; /* flag to indicate restricted mode */
+int nohighlight = FALSE; /* turns off highlighting */
+int eightbit = TRUE; /* eight bit character flag */
+int local_LINES = 0; /* copy of LINES, to detect when win resizes */
+int local_COLS = 0; /* copy of COLS, to detect when win resizes */
+int curses_initialized = FALSE; /* flag indicating if curses has been started*/
+int emacs_keys_mode = FALSE; /* mode for if emacs key binings are used */
+
+char *point; /* points to current position in line */
+char *srch_str; /* pointer for search string */
+char *u_srch_str; /* pointer to non-case sensitive search */
+char *srch_1; /* pointer to start of suspect string */
+char *srch_2; /* pointer to next character of string */
+char *srch_3;
+char *in_file_name = NULL; /* name of input file */
+char *tmp_file; /* temporary file name */
+char d_char; /* deleted character */
+char *d_word; /* deleted word */
+char *d_line; /* deleted line */
+char in_string[513]; /* buffer for reading a file */
+char *print_command = "lp"; /* string to use for the print command */
+char *start_at_line = NULL; /* move to this line at start of session*/
+int in; /* input character */
+
+FILE *temp_fp; /* temporary file pointer */
+FILE *bit_bucket; /* file pointer to /dev/null */
+
+char *table[] = {
+ "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "\t", "^J",
+ "^K", "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U",
+ "^V", "^W", "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_"
+ };
+
+WINDOW *com_win;
+WINDOW *text_win;
+WINDOW *help_win;
+WINDOW *info_win;
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define P_(s) s
+#else
+#define P_(s) ()
+#endif
+
+
+/*
+ | The following structure allows menu items to be flexibly declared.
+ | The first item is the string describing the selection, the second
+ | is the address of the procedure to call when the item is selected,
+ | and the third is the argument for the procedure.
+ |
+ | For those systems with i18n, the string should be accompanied by a
+ | catalog number. The 'int *' should be replaced with 'void *' on
+ | systems with that type.
+ |
+ | The first menu item will be the title of the menu, with NULL
+ | parameters for the procedure and argument, followed by the menu items.
+ |
+ | If the procedure value is NULL, the menu item is displayed, but no
+ | procedure is called when the item is selected. The number of the
+ | item will be returned. If the third (argument) parameter is -1, no
+ | argument is given to the procedure when it is called.
+ */
+
+struct menu_entries {
+ char *item_string;
+ int (*procedure)P_((struct menu_entries *));
+ struct menu_entries *ptr_argument;
+ int (*iprocedure)P_((int));
+ void (*nprocedure)P_((void));
+ unsigned int argument;
+ };
+
+int main P_((int argc, char *argv[]));
+char *resiz_line P_((int factor, struct text *rline, int rpos));
+void insert P_((int character));
+void delete P_((int disp));
+void scanline P_((char *pos));
+int tabshift P_((int temp_int));
+int out_char P_((WINDOW *window, int character, int column));
+int len_char P_((int character, int column));
+void draw_line P_((int vertical, int horiz, char *ptr, int t_pos, int length));
+void insert_line P_((int disp));
+struct text *txtalloc P_((void));
+struct files *name_alloc P_((void));
+char *next_word P_((char *string));
+void prev_word P_((void));
+void control P_((void));
+void emacs_control P_((void));
+void bottom P_((void));
+void top P_((void));
+void nextline P_((void));
+void prevline P_((void));
+void left P_((int disp));
+void right P_((int disp));
+void find_pos P_((void));
+void up P_((void));
+void down P_((void));
+void function_key P_((void));
+void print_buffer P_((void));
+void command_prompt P_((void));
+void command P_((char *cmd_str1));
+int scan P_((char *line, int offset, int column));
+char *get_string P_((char *prompt, int advance));
+int compare P_((char *string1, char *string2, int sensitive));
+void goto_line P_((char *cmd_str));
+void midscreen P_((int line, char *pnt));
+void get_options P_((int numargs, char *arguments[]));
+void check_fp P_((void));
+void get_file P_((char *file_name));
+void get_line P_((int length, char *in_string, int *append));
+void draw_screen P_((void));
+void finish P_((void));
+int quit P_((int noverify));
+void edit_abort P_((int arg));
+void delete_text P_((void));
+int write_file P_((char *file_name));
+int search P_((int display_message));
+void search_prompt P_((void));
+void del_char P_((void));
+void undel_char P_((void));
+void del_word P_((void));
+void undel_word P_((void));
+void del_line P_((void));
+void undel_line P_((void));
+void adv_word P_((void));
+void move_rel P_((char *direction, int lines));
+void eol P_((void));
+void bol P_((void));
+void adv_line P_((void));
+void sh_command P_((char *string));
+void set_up_term P_((void));
+void resize_check P_((void));
+int menu_op P_((struct menu_entries *));
+void help P_((void));
+void paint_info_win P_((void));
+void no_info_window P_((void));
+void create_info_window P_((void));
+int file_op P_((int arg));
+void shell_op P_((void));
+void leave_op P_((void));
+void redraw P_((void));
+int Blank_Line P_((struct text *test_line));
+void Format P_((void));
+void ee_init P_((void));
+void echo_string P_((char *string));
+void spell_op P_((void));
+void ispell_op P_((void));
+int first_word_len P_((struct text *test_line));
+void Auto_Format P_((void));
+void modes_op P_((void));
+char *is_in_string P_((char *string, char *substring));
+char *resolve_name P_((char *name));
+int restrict_mode P_((void));
+int unique_test P_((char *string, char *list[]));
+void strings_init P_((void));
+
+#undef P_
+/*
+ | allocate space here for the strings that will be in the menu
+ */
+
+struct menu_entries modes_menu[] = {
+ {"", NULL, NULL, NULL, NULL, 0},
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, NULL, -1},
+ {NULL, NULL, NULL, NULL, NULL, -1}
+ };
+
+char *mode_strings[9];
+
+#define NUM_MODES_ITEMS 9
+
+struct menu_entries leave_menu[] = {
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, finish, -1},
+ {"", NULL, NULL, quit, NULL, TRUE},
+ {NULL, NULL, NULL, NULL, NULL, -1}
+ };
+
+#define READ_FILE 1
+#define WRITE_FILE 2
+#define SAVE_FILE 3
+
+struct menu_entries file_menu[] = {
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, file_op, NULL, READ_FILE},
+ {"", NULL, NULL, file_op, NULL, WRITE_FILE},
+ {"", NULL, NULL, file_op, NULL, SAVE_FILE},
+ {"", NULL, NULL, NULL, print_buffer, -1},
+ {NULL, NULL, NULL, NULL, NULL, -1}
+ };
+
+struct menu_entries search_menu[] = {
+ {"", NULL, NULL, NULL, NULL, 0},
+ {"", NULL, NULL, NULL, search_prompt, -1},
+ {"", NULL, NULL, search, NULL, TRUE},
+ {NULL, NULL, NULL, NULL, NULL, -1}
+ };
+
+struct menu_entries spell_menu[] = {
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, spell_op, -1},
+ {"", NULL, NULL, NULL, ispell_op, -1},
+ {NULL, NULL, NULL, NULL, NULL, -1}
+ };
+
+struct menu_entries misc_menu[] = {
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, Format, -1},
+ {"", NULL, NULL, NULL, shell_op, -1},
+ {"", menu_op, spell_menu, NULL, NULL, -1},
+ {NULL, NULL, NULL, NULL, NULL, -1}
+ };
+
+struct menu_entries main_menu[] = {
+ {"", NULL, NULL, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, leave_op, -1},
+ {"", NULL, NULL, NULL, help, -1},
+ {"", menu_op, file_menu, NULL, NULL, -1},
+ {"", NULL, NULL, NULL, redraw, -1},
+ {"", NULL, NULL, NULL, modes_op, -1},
+ {"", menu_op, search_menu, NULL, NULL, -1},
+ {"", menu_op, misc_menu, NULL, NULL, -1},
+ {NULL, NULL, NULL, NULL, NULL, -1}
+ };
+
+char *help_text[22];
+char *control_keys[5];
+
+char *emacs_help_text[22];
+char *emacs_control_keys[5];
+
+char *command_strings[5];
+char *commands[30];
+char *init_strings[20];
+
+/*
+ | Declarations for strings for localization
+ */
+
+char *com_win_message; /* to be shown in com_win if no info window */
+char *no_file_string;
+char *ascii_code_str;
+char *printer_msg_str;
+char *command_str;
+char *file_write_prompt_str;
+char *file_read_prompt_str;
+char *char_str;
+char *unkn_cmd_str;
+char *non_unique_cmd_msg;
+char *line_num_str;
+char *line_len_str;
+char *current_file_str;
+char *usage0;
+char *usage1;
+char *usage2;
+char *usage3;
+char *usage4;
+char *file_is_dir_msg;
+char *new_file_msg;
+char *cant_open_msg;
+char *open_file_msg;
+char *file_read_fin_msg;
+char *reading_file_msg;
+char *read_only_msg;
+char *file_read_lines_msg;
+char *save_file_name_prompt;
+char *file_not_saved_msg;
+char *changes_made_prompt;
+char *yes_char;
+char *file_exists_prompt;
+char *create_file_fail_msg;
+char *writing_file_msg;
+char *file_written_msg;
+char *searching_msg;
+char *str_not_found_msg;
+char *search_prompt_str;
+char *exec_err_msg;
+char *continue_msg;
+char *menu_cancel_msg;
+char *menu_size_err_msg;
+char *press_any_key_msg;
+char *shell_prompt;
+char *formatting_msg;
+char *shell_echo_msg;
+char *spell_in_prog_msg;
+char *margin_prompt;
+char *restricted_msg;
+char *ON;
+char *OFF;
+char *HELP;
+char *WRITE;
+char *READ;
+char *LINE;
+char *FILE_str;
+char *CHARACTER;
+char *REDRAW;
+char *RESEQUENCE;
+char *AUTHOR;
+char *VERSION;
+char *CASE;
+char *NOCASE;
+char *EXPAND;
+char *NOEXPAND;
+char *Exit_string;
+char *QUIT_string;
+char *INFO;
+char *NOINFO;
+char *MARGINS;
+char *NOMARGINS;
+char *AUTOFORMAT;
+char *NOAUTOFORMAT;
+char *Echo;
+char *PRINTCOMMAND;
+char *RIGHTMARGIN;
+char *HIGHLIGHT;
+char *NOHIGHLIGHT;
+char *EIGHTBIT;
+char *NOEIGHTBIT;
+char *EMACS_string;
+char *NOEMACS_string;
+
+#ifndef __STDC__
+#ifndef HAS_STDLIB
+extern char *malloc();
+extern char *realloc();
+extern char *getenv();
+FILE *fopen(); /* declaration for open function */
+#endif /* HAS_STDLIB */
+#endif /* __STDC__ */
+
+int
+main(argc, argv) /* beginning of main program */
+int argc;
+char *argv[];
+{
+ int counter;
+
+ for (counter = 1; counter < 24; counter++)
+ signal(counter, SIG_IGN);
+
+ signal(SIGCHLD, SIG_DFL);
+ signal(SIGSEGV, SIG_DFL);
+ signal(SIGINT, edit_abort);
+
+ d_char = 0;
+ d_word = malloc(150);
+ *d_word = (char) NULL;
+ d_line = NULL;
+ dlt_line = txtalloc();
+ dlt_line->line = d_line;
+ curr_line = first_line = txtalloc();
+ curr_line->line = point = malloc(10);
+ curr_line->line_length = 1;
+ curr_line->max_length = 10;
+ curr_line->prev_line = NULL;
+ curr_line->next_line = NULL;
+ curr_line->line_number = 1;
+ srch_str = NULL;
+ u_srch_str = NULL;
+ position = 1;
+ scr_pos =0;
+ scr_vert = 0;
+ scr_horz = 0;
+ bit_bucket = fopen("/dev/null", "w");
+ edit = TRUE;
+ gold = case_sen = FALSE;
+ shell_fork = TRUE;
+ strings_init();
+ ee_init();
+ if (argc > 0 )
+ get_options(argc, argv);
+ set_up_term();
+ if (right_margin == 0)
+ right_margin = COLS - 1;
+ if (top_of_stack == NULL)
+ {
+ wprintw(com_win, no_file_string);
+ wrefresh(com_win);
+ }
+ else
+ check_fp();
+
+ clear_com_win = TRUE;
+
+ while(edit)
+ {
+ wrefresh(text_win);
+ in = wgetch(text_win);
+ if (in == -1)
+ exit(0);
+
+ resize_check();
+
+ if (clear_com_win)
+ {
+ clear_com_win = FALSE;
+ wmove(com_win, 0, 0);
+ werase(com_win);
+ if (!info_window)
+ {
+ wprintw(com_win, "%s", com_win_message);
+ }
+ wrefresh(com_win);
+ }
+
+ if (in > 255)
+ function_key();
+ else if ((in == '\10') || (in == 127))
+ delete(TRUE);
+ else if ((in > 31) || (in == 9))
+ insert(in);
+ else if ((in >= 0) && (in <= 31))
+ {
+ if (emacs_keys_mode)
+ emacs_control();
+ else
+ control();
+ }
+ }
+ return(0);
+}
+
+char *
+resiz_line(factor, rline, rpos) /* resize the line to length + factor*/
+int factor; /* resize factor */
+struct text *rline; /* position in line */
+int rpos;
+{
+ char *rpoint;
+ int resiz_var;
+
+ rline->max_length += factor;
+ rpoint = rline->line = realloc(rline->line, rline->max_length );
+ for (resiz_var = 1 ; (resiz_var < rpos) ; resiz_var++)
+ rpoint++;
+ return(rpoint);
+}
+
+void
+insert(character) /* insert character into line */
+int character; /* new character */
+{
+ int counter;
+ int value;
+ char *temp; /* temporary pointer */
+ char *temp2; /* temporary pointer */
+
+ if ((character == '\011') && (expand_tabs))
+ {
+ counter = len_char('\011', scr_horz);
+ for (; counter > 0; counter--)
+ insert(' ');
+ if (auto_format)
+ Auto_Format();
+ return;
+ }
+ text_changes = TRUE;
+ if ((curr_line->max_length - curr_line->line_length) < 5)
+ point = resiz_line(10, curr_line, position);
+ curr_line->line_length++;
+ temp = point;
+ counter = position;
+ while (counter < curr_line->line_length) /* find end of line */
+ {
+ counter++;
+ temp++;
+ }
+ temp++; /* increase length of line by one */
+ while (point < temp)
+ {
+ temp2=temp - 1;
+ *temp= *temp2; /* shift characters over by one */
+ temp--;
+ }
+ *point = character; /* insert new character */
+ wclrtoeol(text_win);
+ if (((character >= 0) && (character < ' ')) || (character >= 127)) /* check for TAB character*/
+ {
+ scr_pos = scr_horz += out_char(text_win, character, scr_horz);
+ point++;
+ position++;
+ }
+ else
+ {
+ waddch(text_win, character);
+ scr_pos = ++scr_horz;
+ point++;
+ position ++;
+ }
+
+ if ((observ_margins) && (right_margin < scr_pos))
+ {
+ counter = position;
+ while (scr_pos > right_margin)
+ prev_word();
+ if (scr_pos == 0)
+ {
+ while (position < counter)
+ right(TRUE);
+ }
+ else
+ {
+ counter -= position;
+ insert_line(TRUE);
+ for (value = 0; value < counter; value++)
+ right(TRUE);
+ }
+ }
+
+ if ((scr_horz - horiz_offset) > last_col)
+ {
+ horiz_offset += 8;
+ midscreen(scr_vert, point);
+ }
+
+ if ((auto_format) && (character == ' ') && (!formatted))
+ Auto_Format();
+ else if ((character != ' ') && (character != '\t'))
+ formatted = FALSE;
+
+ draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
+}
+
+void
+delete(disp) /* delete character */
+int disp;
+{
+ char *tp;
+ char *temp2;
+ struct text *temp_buff;
+ int temp_vert;
+ int temp_pos;
+
+ if (point != curr_line->line) /* if not at beginning of line */
+ {
+ text_changes = TRUE;
+ temp2 = tp = point;
+ tp--;
+ point--;
+ if ((*tp >= '\000') && (*tp < ' ')) /* check for TAB */
+ scanline(tp);
+ else
+ --scr_horz;
+ scr_pos = scr_horz;
+ if (in == 8)
+ d_char = *point; /* save deleted character */
+ temp_pos = --position;
+ curr_line->line_length--;
+ while (temp_pos <= curr_line->line_length)
+ {
+ temp_pos++;
+ *tp= *temp2;
+ tp++;
+ temp2++;
+ }
+ if (scr_horz < horiz_offset)
+ {
+ horiz_offset -= 8;
+ midscreen(scr_vert, point);
+ }
+ }
+ else if (curr_line->prev_line != NULL)
+ {
+ text_changes = TRUE;
+ left(disp); /* go to previous line */
+ temp_buff = curr_line->next_line;
+ point = resiz_line(temp_buff->line_length, curr_line, position);
+ if (temp_buff->next_line != NULL)
+ temp_buff->next_line->prev_line = curr_line;
+ curr_line->next_line = temp_buff->next_line;
+ temp2 = temp_buff->line;
+ if (in == 8)
+ d_char = '\n';
+ tp = point;
+ temp_pos = 1;
+ while (temp_pos < temp_buff->line_length)
+ {
+ curr_line->line_length++;
+ temp_pos++;
+ *tp = *temp2;
+ tp++;
+ temp2++;
+ }
+ *tp = (char) NULL;
+ free(temp_buff->line);
+ free(temp_buff);
+ temp_buff = curr_line;
+ temp_vert = scr_vert;
+ scr_pos = scr_horz;
+ if (scr_vert < last_line)
+ {
+ wmove(text_win, scr_vert + 1, 0);
+ wdeleteln(text_win);
+ }
+ while ((temp_buff != NULL) && (temp_vert < last_line))
+ {
+ temp_buff = temp_buff->next_line;
+ temp_vert++;
+ }
+ if ((temp_vert == last_line) && (temp_buff != NULL))
+ {
+ tp = temp_buff->line;
+ wmove(text_win, last_line,0);
+ wclrtobot(text_win);
+ draw_line(last_line, 0, tp, 1, temp_buff->line_length);
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+ }
+ }
+ draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
+ formatted = FALSE;
+}
+
+void
+scanline(pos) /* find the proper horizontal position for the pointer */
+char *pos;
+{
+ int temp;
+ char *ptr;
+
+ ptr = curr_line->line;
+ temp = 0;
+ while (ptr < pos)
+ {
+ if ((*ptr >= 0) && (*ptr <= 8))
+ temp += 2;
+ else if (*ptr == 9)
+ temp += tabshift(temp);
+ else if ((*ptr >= 10) && (*ptr <= 31))
+ temp += 2;
+ else if ((*ptr >= 32) && (*ptr < 127))
+ temp++;
+ else if (*ptr == 127)
+ temp += 2;
+ else if (!eightbit)
+ temp += 5;
+ else
+ temp++;
+ ptr++;
+ }
+ scr_horz = temp;
+ if ((scr_horz - horiz_offset) > last_col)
+ {
+ horiz_offset = (scr_horz - (scr_horz % 8)) - (COLS - 8);
+ midscreen(scr_vert, point);
+ }
+ else if (scr_horz < horiz_offset)
+ {
+ horiz_offset = max(0, (scr_horz - (scr_horz % 8)));
+ midscreen(scr_vert, point);
+ }
+}
+
+int
+tabshift(temp_int) /* give the number of spaces to shift */
+int temp_int;
+{
+ int leftover;
+
+ leftover = ((temp_int + 1) % 8);
+ if (leftover == 0)
+ return (1);
+ else
+ return (9 - leftover);
+}
+
+int
+out_char(window, character, column) /* output non-printing character */
+WINDOW *window;
+char character;
+int column;
+{
+ int i1, i2;
+ char *string;
+ char string2[8];
+
+ if (character == TAB)
+ {
+ i1 = tabshift(column);
+ for (i2 = 0;
+ (i2 < i1) && (((column+i2+1)-horiz_offset) < last_col); i2++)
+ {
+ waddch(window, ' ');
+ }
+ return(i1);
+ }
+ else if ((character >= '\0') && (character < ' '))
+ {
+ string = table[(int) character];
+ }
+ else if ((character < 0) || (character >= 127))
+ {
+ if (character == 127)
+ string = "^?";
+ else if (!eightbit)
+ {
+ sprintf(string2, "<%d>", (character < 0) ? (character + 256) : character);
+ string = string2;
+ }
+ else
+ {
+ waddch(window, character & 0xFF);
+ return(1);
+ }
+ }
+ else
+ {
+ waddch(window, character);
+ return(1);
+ }
+ for (i2 = 0; (string[i2] != (char) NULL) && (((column+i2+1)-horiz_offset) < last_col); i2++)
+ waddch(window, string[i2]);
+ return(strlen(string));
+}
+
+int
+len_char(character, column) /* return the length of the character */
+char character;
+int column; /* the column must be known to provide spacing for tabs */
+{
+ int length;
+
+ if (character == '\t')
+ length = tabshift(column);
+ else if ((character >= 0) && (character < 32))
+ length = 2;
+ else if ((character >= 32) && (character <= 126))
+ length = 1;
+ else if (character == 127)
+ length = 2;
+ else if (((character > 126) || (character < 0)) && (!eightbit))
+ length = 5;
+ else
+ length = 1;
+
+ return(length);
+}
+
+void
+draw_line(vertical, horiz, ptr, t_pos, length) /* redraw line from current position */
+int vertical; /* current vertical position on screen */
+int horiz; /* current horizontal position on screen */
+char *ptr; /* pointer to line */
+int t_pos; /* current position (offset in bytes) from bol */
+int length; /* length (in bytes) of line */
+{
+ int d; /* partial length of special or tab char to display */
+ char *temp; /* temporary pointer to position in line */
+ int abs_column; /* offset in screen units from begin of line */
+ int column; /* horizontal position on screen */
+ int row; /* vertical position on screen */
+ int posit; /* temporary position indicator within line */
+
+ abs_column = horiz;
+ column = horiz - horiz_offset;
+ row = vertical;
+ temp = ptr;
+ d = 0;
+ posit = t_pos;
+ if (column < 0)
+ {
+ wmove(text_win, row, 0);
+ wclrtoeol(text_win);
+ }
+ while (column < 0)
+ {
+ d = len_char(*temp, abs_column);
+ abs_column += d;
+ column += d;
+ posit++;
+ temp++;
+ }
+ wmove(text_win, row, column);
+ wclrtoeol(text_win);
+ while ((posit < length) && (column <= last_col))
+ {
+ if ((*temp < 32) || (*temp == 127))
+ {
+ column += len_char(*temp, abs_column);
+ abs_column += out_char(text_win, *temp, abs_column);
+ }
+ else
+ {
+ abs_column++;
+ column++;
+ waddch(text_win, *temp);
+ }
+ posit++;
+ temp++;
+ }
+ if (column < last_col)
+ wclrtoeol(text_win);
+ wmove(text_win, vertical, (horiz - horiz_offset));
+}
+
+void
+insert_line(disp) /* insert new line */
+int disp;
+{
+ int temp_pos;
+ int temp_pos2;
+ char *temp;
+ char *extra;
+ struct text *temp_nod;
+
+ text_changes = TRUE;
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+ wclrtoeol(text_win);
+ temp_nod= txtalloc();
+ temp_nod->line = extra= malloc(10);
+ temp_nod->line_length = 1;
+ temp_nod->max_length = 10;
+ temp_nod->line_number = curr_line->line_number + 1;
+ temp_nod->next_line = curr_line->next_line;
+ if (temp_nod->next_line != NULL)
+ temp_nod->next_line->prev_line = temp_nod;
+ temp_nod->prev_line = curr_line;
+ curr_line->next_line = temp_nod;
+ temp_pos2 = position;
+ temp = point;
+ if (temp_pos2 < curr_line->line_length)
+ {
+ temp_pos = 1;
+ while (temp_pos2 < curr_line->line_length)
+ {
+ if ((temp_nod->max_length - temp_nod->line_length)< 5)
+ extra = resiz_line(10, temp_nod, temp_pos);
+ temp_nod->line_length++;
+ temp_pos++;
+ temp_pos2++;
+ *extra= *temp;
+ extra++;
+ temp++;
+ }
+ temp=point;
+ *temp = (char) NULL;
+ temp = resiz_line((1 - temp_nod->line_length), curr_line, position);
+ curr_line->line_length = 1 + temp - curr_line->line;
+ }
+ curr_line->line_length = position;
+ curr_line = temp_nod;
+ *extra = (char) NULL;
+ position = 1;
+ point= curr_line->line;
+ if (disp)
+ {
+ if (scr_vert < last_line)
+ {
+ scr_vert++;
+ wclrtoeol(text_win);
+ wmove(text_win, scr_vert, 0);
+ winsertln(text_win);
+ }
+ else
+ {
+ wmove(text_win, 0,0);
+ wdeleteln(text_win);
+ wmove(text_win, last_line,0);
+ wclrtobot(text_win);
+ }
+ scr_pos = scr_horz = 0;
+ if (horiz_offset)
+ {
+ horiz_offset = 0;
+ midscreen(scr_vert, point);
+ }
+ draw_line(scr_vert, scr_horz, point, position,
+ curr_line->line_length);
+ }
+}
+
+struct text *txtalloc() /* allocate space for line structure */
+{
+ return((struct text *) malloc(sizeof( struct text)));
+}
+
+struct files *name_alloc() /* allocate space for file name list node */
+{
+ return((struct files *) malloc(sizeof( struct files)));
+}
+
+char *next_word(string) /* move to next word in string */
+char *string;
+{
+ while ((*string != (char) NULL) && ((*string != 32) && (*string != 9)))
+ string++;
+ while ((*string != (char) NULL) && ((*string == 32) || (*string == 9)))
+ string++;
+ return(string);
+}
+
+void
+prev_word() /* move to start of previous word in text */
+{
+ if (position != 1)
+ {
+ if ((position != 1) && ((point[-1] == ' ') || (point[-1] == '\t')))
+ { /* if at the start of a word */
+ while ((position != 1) && ((*point != ' ') && (*point != '\t')))
+ left(TRUE);
+ }
+ while ((position != 1) && ((*point == ' ') || (*point == '\t')))
+ left(TRUE);
+ while ((position != 1) && ((*point != ' ') && (*point != '\t')))
+ left(TRUE);
+ if ((position != 1) && ((*point == ' ') || (*point == '\t')))
+ right(TRUE);
+ }
+ else
+ left(TRUE);
+}
+
+void
+control() /* use control for commands */
+{
+ char *string;
+
+ if (in == 1) /* control a */
+ {
+ string = get_string(ascii_code_str, TRUE);
+ if (*string != (char) NULL)
+ {
+ in = atoi(string);
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+ insert(in);
+ }
+ free(string);
+ }
+ else if (in == 2) /* control b */
+ bottom();
+ else if (in == 3) /* control c */
+ {
+ command_prompt();
+ }
+ else if (in == 4) /* control d */
+ down();
+ else if (in == 5) /* control e */
+ search_prompt();
+ else if (in == 6) /* control f */
+ undel_char();
+ else if (in == 7) /* control g */
+ bol();
+ else if (in == 8) /* control h */
+ delete(TRUE);
+ else if (in == 9) /* control i */
+ ;
+ else if (in == 10) /* control j */
+ insert_line(TRUE);
+ else if (in == 11) /* control k */
+ del_char();
+ else if (in == 12) /* control l */
+ left(TRUE);
+ else if (in == 13) /* control m */
+ insert_line(TRUE);
+ else if (in == 14) /* control n */
+ move_rel("d", max(5, (last_line - 5)));
+ else if (in == 15) /* control o */
+ eol();
+ else if (in == 16) /* control p */
+ move_rel("u", max(5, (last_line - 5)));
+ else if (in == 17) /* control q */
+ ;
+ else if (in == 18) /* control r */
+ right(TRUE);
+ else if (in == 19) /* control s */
+ ;
+ else if (in == 20) /* control t */
+ top();
+ else if (in == 21) /* control u */
+ up();
+ else if (in == 22) /* control v */
+ undel_word();
+ else if (in == 23) /* control w */
+ del_word();
+ else if (in == 24) /* control x */
+ search(TRUE);
+ else if (in == 25) /* control y */
+ del_line();
+ else if (in == 26) /* control z */
+ undel_line();
+ else if (in == 27) /* control [ (escape) */
+ {
+ menu_op(main_menu);
+ }
+}
+
+/*
+ | Emacs control-key bindings
+ */
+
+void
+emacs_control()
+{
+ char *string;
+
+ if (in == 1) /* control a */
+ bol();
+ else if (in == 2) /* control b */
+ left(TRUE);
+ else if (in == 3) /* control c */
+ {
+ command_prompt();
+ }
+ else if (in == 4) /* control d */
+ del_char();
+ else if (in == 5) /* control e */
+ eol();
+ else if (in == 6) /* control f */
+ right(TRUE);
+ else if (in == 7) /* control g */
+ move_rel("u", max(5, (last_line - 5)));
+ else if (in == 8) /* control h */
+ delete(TRUE);
+ else if (in == 9) /* control i */
+ ;
+ else if (in == 10) /* control j */
+ undel_char();
+ else if (in == 11) /* control k */
+ del_line();
+ else if (in == 12) /* control l */
+ undel_line();
+ else if (in == 13) /* control m */
+ insert_line(TRUE);
+ else if (in == 14) /* control n */
+ down();
+ else if (in == 15) /* control o */
+ {
+ string = get_string(ascii_code_str, TRUE);
+ if (*string != (char) NULL)
+ {
+ in = atoi(string);
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+ insert(in);
+ }
+ free(string);
+ }
+ else if (in == 16) /* control p */
+ up();
+ else if (in == 17) /* control q */
+ ;
+ else if (in == 18) /* control r */
+ undel_word();
+ else if (in == 19) /* control s */
+ ;
+ else if (in == 20) /* control t */
+ top();
+ else if (in == 21) /* control u */
+ bottom();
+ else if (in == 22) /* control v */
+ move_rel("d", max(5, (last_line - 5)));
+ else if (in == 23) /* control w */
+ del_word();
+ else if (in == 24) /* control x */
+ search(TRUE);
+ else if (in == 25) /* control y */
+ search_prompt();
+ else if (in == 26) /* control z */
+ adv_word();
+ else if (in == 27) /* control [ (escape) */
+ {
+ menu_op(main_menu);
+ }
+}
+
+void
+bottom() /* go to bottom of file */
+{
+ while (curr_line->next_line != NULL)
+ curr_line = curr_line->next_line;
+ point = curr_line->line;
+ if (horiz_offset)
+ horiz_offset = 0;
+ position = 1;
+ midscreen(last_line, point);
+ scr_pos = scr_horz;
+}
+
+void
+top() /* go to top of file */
+{
+ while (curr_line->prev_line != NULL)
+ curr_line = curr_line->prev_line;
+ point = curr_line->line;
+ if (horiz_offset)
+ horiz_offset = 0;
+ position = 1;
+ midscreen(0, point);
+ scr_pos = scr_horz;
+}
+
+void
+nextline() /* move pointers to start of next line */
+{
+ curr_line = curr_line->next_line;
+ point = curr_line->line;
+ position = 1;
+ if (scr_vert == last_line)
+ {
+ wmove(text_win, 0,0);
+ wdeleteln(text_win);
+ wmove(text_win, last_line,0);
+ wclrtobot(text_win);
+ draw_line(last_line,0,point,1,curr_line->line_length);
+ }
+ else
+ scr_vert++;
+}
+
+void
+prevline() /* move pointers to start of previous line*/
+{
+ curr_line = curr_line->prev_line;
+ point = curr_line->line;
+ position = 1;
+ if (scr_vert == 0)
+ {
+ winsertln(text_win);
+ draw_line(0,0,point,1,curr_line->line_length);
+ }
+ else
+ scr_vert--;
+ while (position < curr_line->line_length)
+ {
+ position++;
+ point++;
+ }
+}
+
+void
+left(disp) /* move left one character */
+int disp;
+{
+ if (point != curr_line->line) /* if not at begin of line */
+ {
+ point--;
+ position--;
+ scanline(point);
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+ scr_pos = scr_horz;
+ }
+ else if (curr_line->prev_line != NULL)
+ {
+ if (!disp)
+ {
+ curr_line = curr_line->prev_line;
+ point = curr_line->line + curr_line->line_length;
+ position = curr_line->line_length;
+ return;
+ }
+ position = 1;
+ prevline();
+ scanline(point);
+ scr_pos = scr_horz;
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+ }
+}
+
+void
+right(disp) /* move right one character */
+int disp;
+{
+ if (position < curr_line->line_length)
+ {
+ point++;
+ position++;
+ scanline(point);
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+ scr_pos = scr_horz;
+ }
+ else if (curr_line->next_line != NULL)
+ {
+ if (!disp)
+ {
+ curr_line = curr_line->next_line;
+ point = curr_line->line;
+ position = 1;
+ return;
+ }
+ nextline();
+ scr_pos = scr_horz = 0;
+ if (horiz_offset)
+ {
+ horiz_offset = 0;
+ midscreen(scr_vert, point);
+ }
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+ position = 1;
+ }
+}
+
+void
+find_pos() /* move to the same column as on other line */
+{
+ scr_horz = 0;
+ position = 1;
+ while ((scr_horz < scr_pos) && (position < curr_line->line_length))
+ {
+ if (*point == 9)
+ scr_horz += tabshift(scr_horz);
+ else if ((*point >= '\0') && (*point < ' '))
+ scr_horz += 2;
+ else
+ scr_horz++;
+ position++;
+ point++;
+ }
+ if ((scr_horz - horiz_offset) > last_col)
+ {
+ horiz_offset = (scr_horz - (scr_horz % 8)) - (COLS - 8);
+ midscreen(scr_vert, point);
+ }
+ else if (scr_horz < horiz_offset)
+ {
+ horiz_offset = max(0, (scr_horz - (scr_horz % 8)));
+ midscreen(scr_vert, point);
+ }
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void
+up() /* move up one line */
+{
+ if (curr_line->prev_line != NULL)
+ {
+ prevline();
+ point = curr_line->line;
+ find_pos();
+ }
+}
+
+void
+down() /* move down one line */
+{
+ if (curr_line->next_line != NULL)
+ {
+ nextline();
+ find_pos();
+ }
+}
+
+void
+function_key() /* process function key */
+{
+ if (in == KEY_LEFT)
+ left(TRUE);
+ else if (in == KEY_RIGHT)
+ right(TRUE);
+ else if ( in == KEY_HOME)
+ top();
+ else if ( in == KEY_UP)
+ up();
+ else if (in == KEY_DOWN)
+ down();
+ else if (in == KEY_NPAGE)
+ move_rel("d", max( 5, (last_line - 5)));
+ else if (in == KEY_PPAGE)
+ move_rel("u", max(5, (last_line - 5)));
+ else if (in == KEY_DL)
+ del_line();
+ else if (in == KEY_DC)
+ del_char();
+ else if (in == KEY_BACKSPACE)
+ delete(TRUE);
+ else if (in == KEY_IL)
+ { /* insert a line before current line */
+ insert_line(TRUE);
+ left(TRUE);
+ }
+ else if (in == KEY_F(1))
+ gold = !gold;
+ else if (in == KEY_F(2))
+ {
+ if (gold)
+ {
+ gold = FALSE;
+ undel_line();
+ }
+ else
+ undel_char();
+ }
+ else if (in == KEY_F(3))
+ {
+ if (gold)
+ {
+ gold = FALSE;
+ undel_word();
+ }
+ else
+ del_word();
+ }
+ else if (in == KEY_F(4))
+ {
+ if (gold)
+ {
+ gold = FALSE;
+ paint_info_win();
+ midscreen(scr_vert, point);
+ }
+ else
+ adv_word();
+ }
+ else if (in == KEY_F(5))
+ {
+ if (gold)
+ {
+ gold = FALSE;
+ search_prompt();
+ }
+ else
+ search(TRUE);
+ }
+ else if (in == KEY_F(6))
+ {
+ if (gold)
+ {
+ gold = FALSE;
+ bottom();
+ }
+ else
+ top();
+ }
+ else if (in == KEY_F(7))
+ {
+ if (gold)
+ {
+ gold = FALSE;
+ eol();
+ }
+ else
+ bol();
+ }
+ else if (in == KEY_F(8))
+ {
+ if (gold)
+ {
+ gold = FALSE;
+ command_prompt();
+ }
+ else
+ adv_line();
+ }
+}
+
+void
+print_buffer()
+{
+ char buffer[256];
+
+ sprintf(buffer, ">!%s", print_command);
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, printer_msg_str, print_command);
+ wrefresh(com_win);
+ command(buffer);
+}
+
+void
+command_prompt()
+{
+ char *cmd_str;
+ int result;
+
+ info_type = COMMANDS;
+ paint_info_win();
+ cmd_str = get_string(command_str, TRUE);
+ if ((result = unique_test(cmd_str, commands)) != 1)
+ {
+ werase(com_win);
+ wmove(com_win, 0, 0);
+ if (result == 0)
+ wprintw(com_win, unkn_cmd_str, cmd_str);
+ else
+ wprintw(com_win, non_unique_cmd_msg);
+
+ wrefresh(com_win);
+
+ info_type = CONTROL_KEYS;
+ paint_info_win();
+
+ if (cmd_str != NULL)
+ free(cmd_str);
+ return;
+ }
+ command(cmd_str);
+ wrefresh(com_win);
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+ info_type = CONTROL_KEYS;
+ paint_info_win();
+ if (cmd_str != NULL)
+ free(cmd_str);
+}
+
+void
+command(cmd_str1) /* process commands from keyboard */
+char *cmd_str1;
+{
+ char *cmd_str2 = NULL;
+ char *cmd_str = cmd_str1;
+
+ clear_com_win = TRUE;
+ if (compare(cmd_str, HELP, FALSE))
+ help();
+ else if (compare(cmd_str, WRITE, FALSE))
+ {
+ if (restrict_mode())
+ {
+ return;
+ }
+ cmd_str = next_word(cmd_str);
+ if (*cmd_str == (char) NULL)
+ {
+ cmd_str = cmd_str2 = get_string(file_write_prompt_str, TRUE);
+ }
+ tmp_file = resolve_name(cmd_str);
+ write_file(tmp_file);
+ if (tmp_file != cmd_str)
+ free(tmp_file);
+ }
+ else if (compare(cmd_str, READ, FALSE))
+ {
+ if (restrict_mode())
+ {
+ return;
+ }
+ cmd_str = next_word(cmd_str);
+ if (*cmd_str == (char) NULL)
+ {
+ cmd_str = cmd_str2 = get_string(file_read_prompt_str, TRUE);
+ }
+ tmp_file = cmd_str;
+ recv_file = TRUE;
+ tmp_file = resolve_name(cmd_str);
+ check_fp();
+ if (tmp_file != cmd_str)
+ free(tmp_file);
+ }
+ else if (compare(cmd_str, LINE, FALSE))
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, line_num_str, curr_line->line_number);
+ wprintw(com_win, line_len_str, curr_line->line_length);
+ }
+ else if (compare(cmd_str, FILE_str, FALSE))
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ if (in_file_name == NULL)
+ wprintw(com_win, no_file_string);
+ else
+ wprintw(com_win, current_file_str, in_file_name);
+ }
+ else if ((*cmd_str >= '0') && (*cmd_str <= '9'))
+ goto_line(cmd_str);
+ else if (compare(cmd_str, CHARACTER, FALSE))
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ if (*point >= '\0')
+ wprintw(com_win, char_str, *point);
+ else
+ wprintw(com_win, char_str, (*point + 256));
+ }
+ else if (compare(cmd_str, REDRAW, FALSE))
+ redraw();
+ else if (compare(cmd_str, RESEQUENCE, FALSE))
+ {
+ tmp_line = first_line->next_line;
+ while (tmp_line != NULL)
+ {
+ tmp_line->line_number = tmp_line->prev_line->line_number + 1;
+ tmp_line = tmp_line->next_line;
+ }
+ }
+ else if (compare(cmd_str, AUTHOR, FALSE))
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, "written by Hugh Mahon");
+ }
+ else if (compare(cmd_str, VERSION, FALSE))
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, "%s", version);
+ }
+ else if (compare(cmd_str, CASE, FALSE))
+ case_sen = TRUE;
+ else if (compare(cmd_str, NOCASE, FALSE))
+ case_sen = FALSE;
+ else if (compare(cmd_str, EXPAND, FALSE))
+ expand_tabs = TRUE;
+ else if (compare(cmd_str, NOEXPAND, FALSE))
+ expand_tabs = FALSE;
+ else if (compare(cmd_str, Exit_string, FALSE))
+ finish();
+ else if (compare(cmd_str, QUIT_string, FALSE))
+ quit(0);
+ else if (*cmd_str == '!')
+ {
+ cmd_str++;
+ if ((*cmd_str == ' ') || (*cmd_str == 9))
+ cmd_str = next_word(cmd_str);
+ sh_command(cmd_str);
+ }
+ else if ((*cmd_str == '<') && (!in_pipe))
+ {
+ in_pipe = TRUE;
+ shell_fork = FALSE;
+ cmd_str++;
+ if ((*cmd_str == ' ') || (*cmd_str == '\t'))
+ cmd_str = next_word(cmd_str);
+ command(cmd_str);
+ in_pipe = FALSE;
+ shell_fork = TRUE;
+ }
+ else if ((*cmd_str == '>') && (!out_pipe))
+ {
+ out_pipe = TRUE;
+ cmd_str++;
+ if ((*cmd_str == ' ') || (*cmd_str == '\t'))
+ cmd_str = next_word(cmd_str);
+ command(cmd_str);
+ out_pipe = FALSE;
+ }
+ else
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, unkn_cmd_str, cmd_str);
+ }
+ if (cmd_str2 != NULL)
+ free(cmd_str2);
+}
+
+int
+scan(line, offset, column) /* determine horizontal position for get_string */
+char *line;
+int offset;
+int column;
+{
+ char *stemp;
+ int i;
+ int j;
+
+ stemp = line;
+ i = 0;
+ j = column;
+ while (i < offset)
+ {
+ i++;
+ j += len_char(*stemp, j);
+ stemp++;
+ }
+ return(j);
+}
+
+char *
+get_string(prompt, advance) /* read string from input on command line */
+char *prompt; /* string containing user prompt message */
+int advance; /* if true, skip leading spaces and tabs */
+{
+ char *string;
+ char *tmp_string;
+ char *nam_str;
+ char *g_point;
+ int tmp_int;
+ int g_horz, g_position, g_pos;
+ int esc_flag;
+
+ g_point = tmp_string = malloc(512);
+ wmove(com_win,0,0);
+ wclrtoeol(com_win);
+ waddstr(com_win, prompt);
+ wrefresh(com_win);
+ nam_str = tmp_string;
+ clear_com_win = TRUE;
+ g_horz = g_position = scan(prompt, strlen(prompt), 0);
+ g_pos = 0;
+ keypad(com_win, FALSE);
+ do
+ {
+ esc_flag = FALSE;
+ in = wgetch(com_win);
+ if (in == -1)
+ exit(0);
+ if (((in == 8) || (in == 127)) && (g_pos > 0))
+ {
+ tmp_int = g_horz;
+ g_pos--;
+ g_horz = scan(g_point, g_pos, g_position);
+ tmp_int = tmp_int - g_horz;
+ for (; 0 < tmp_int; tmp_int--)
+ {
+ if ((g_horz+tmp_int) < (last_col - 1))
+ {
+ waddch(com_win, '\010');
+ waddch(com_win, ' ');
+ waddch(com_win, '\010');
+ }
+ }
+ nam_str--;
+ }
+ else if ((in != 8) && (in != 127) && (in != '\n') && (in != '\r'))
+ {
+ if (in == '\026') /* control-v, accept next character verbatim */
+ { /* allows entry of ^m, ^j, and ^h */
+ esc_flag = TRUE;
+ in = wgetch(com_win);
+ if (in == -1)
+ exit(0);
+ }
+ *nam_str = in;
+ g_pos++;
+ if (((in < ' ') || (in > 126)) && (g_horz < (last_col - 1)))
+ g_horz += out_char(com_win, in, g_horz);
+ else
+ {
+ g_horz++;
+ if (g_horz < (last_col - 1))
+ waddch(com_win, in);
+ }
+ nam_str++;
+ }
+ wrefresh(com_win);
+ if (esc_flag)
+ in = (char) NULL;
+ } while ((in != '\n') && (in != '\r'));
+ keypad(com_win, TRUE);
+ *nam_str = (char) NULL;
+ nam_str = tmp_string;
+ if (((*nam_str == ' ') || (*nam_str == 9)) && (advance))
+ nam_str = next_word(nam_str);
+ string = malloc(strlen(nam_str) + 1);
+ strcpy(string, nam_str);
+ free(tmp_string);
+ wrefresh(com_win);
+ return(string);
+}
+
+int
+compare(string1, string2, sensitive) /* compare two strings */
+char *string1;
+char *string2;
+int sensitive;
+{
+ char *strng1;
+ char *strng2;
+ int tmp;
+ int equal;
+
+ strng1 = string1;
+ strng2 = string2;
+ tmp = 0;
+ if ((strng1 == NULL) || (strng2 == NULL) || (*strng1 == (char) NULL) || (*strng2 == (char) NULL))
+ return(FALSE);
+ equal = TRUE;
+ while (equal)
+ {
+ if (sensitive)
+ {
+ if (*strng1 != *strng2)
+ equal = FALSE;
+ }
+ else
+ {
+ if (toupper(*strng1) != toupper(*strng2))
+ equal = FALSE;
+ }
+ strng1++;
+ strng2++;
+ if ((*strng1 == (char) NULL) || (*strng2 == (char) NULL) || (*strng1 == ' ') || (*strng2 == ' '))
+ break;
+ tmp++;
+ }
+ return(equal);
+}
+
+void
+goto_line(cmd_str)
+char *cmd_str;
+{
+ int number;
+ int i;
+ char *ptr;
+ char *direction;
+ struct text *t_line;
+
+ ptr = cmd_str;
+ i= 0;
+ while ((*ptr >='0') && (*ptr <= '9'))
+ {
+ i= i * 10 + (*ptr - '0');
+ ptr++;
+ }
+ number = i;
+ i = 0;
+ t_line = curr_line;
+ while ((t_line->line_number > number) && (t_line->prev_line != NULL))
+ {
+ i++;
+ t_line = t_line->prev_line;
+ direction = "u";
+ }
+ while ((t_line->line_number < number) && (t_line->next_line != NULL))
+ {
+ i++;
+ direction = "d";
+ t_line = t_line->next_line;
+ }
+ if ((i < 30) && (i > 0))
+ {
+ move_rel(direction, i);
+ }
+ else
+ {
+ curr_line = t_line;
+ point = curr_line->line;
+ position = 1;
+ midscreen((last_line / 2), point);
+ scr_pos = scr_horz;
+ }
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, line_num_str, curr_line->line_number);
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void
+midscreen(line, pnt) /* put current line in middle of screen */
+int line;
+char *pnt;
+{
+ struct text *mid_line;
+ int i;
+
+ line = min(line, last_line);
+ mid_line = curr_line;
+ for (i = 0; ((i < line) && (curr_line->prev_line != NULL)); i++)
+ curr_line = curr_line->prev_line;
+ scr_vert = scr_horz = 0;
+ wmove(text_win, 0, 0);
+ draw_screen();
+ scr_vert = i;
+ curr_line = mid_line;
+ scanline(pnt);
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void
+get_options(numargs, arguments) /* get arguments from command line */
+int numargs;
+char *arguments[];
+{
+ char *buff;
+ int count;
+ struct files *temp_names;
+ char *name;
+ char *ptr;
+
+ /*
+ | see if editor was invoked as 'ree' (restricted mode)
+ */
+
+ if (!(name = strrchr(arguments[0], '/')))
+ name = arguments[0];
+ else
+ name++;
+ if (!strcmp(name, "ree"))
+ restricted = TRUE;
+
+ top_of_stack = NULL;
+ input_file = FALSE;
+ recv_file = FALSE;
+ count = 1;
+ while (count < numargs)
+ {
+ buff = arguments[count];
+ if (!strcmp("-i", buff))
+ {
+ info_window = FALSE;
+ }
+ else if (!strcmp("-e", buff))
+ {
+ expand_tabs = FALSE;
+ }
+ else if (!strcmp("-h", buff))
+ {
+ nohighlight = TRUE;
+ }
+ else if (!strcmp("-?", buff))
+ {
+ fprintf(stderr, usage0, arguments[0]);
+ fprintf(stderr, usage1);
+ fprintf(stderr, usage2);
+ fprintf(stderr, usage3);
+ fprintf(stderr, usage4);
+ exit(1);
+ }
+ else if (*buff == '+')
+ {
+ buff++;
+ start_at_line = buff;
+ }
+
+ else
+ {
+ if (top_of_stack == NULL)
+ {
+ temp_names = top_of_stack = name_alloc();
+ }
+ else
+ {
+ temp_names->next_name = name_alloc();
+ temp_names = temp_names->next_name;
+ }
+ ptr = temp_names->name = malloc(strlen(buff) + 1);
+ while (*buff != (char) NULL)
+ {
+ *ptr = *buff;
+ buff++;
+ ptr++;
+ }
+ *ptr = (char) NULL;
+ temp_names->next_name = NULL;
+ input_file = TRUE;
+ recv_file = TRUE;
+ }
+ count++;
+ }
+}
+
+void
+check_fp() /* open or close files according to flags */
+{
+ int line_num;
+ int temp;
+ struct stat buf;
+
+ clear_com_win = TRUE;
+ tmp_vert = scr_vert;
+ tmp_horz = scr_horz;
+ tmp_line = curr_line;
+ if (input_file)
+ {
+ in_file_name = tmp_file = top_of_stack->name;
+ top_of_stack = top_of_stack->next_name;
+ }
+ temp = stat(tmp_file, &buf);
+ buf.st_mode &= ~07777;
+ if ((temp != -1) && (buf.st_mode != 0100000) && (buf.st_mode != 0))
+ {
+ wprintw(com_win, file_is_dir_msg, tmp_file);
+ wrefresh(com_win);
+ if (input_file)
+ {
+ quit(0);
+ return;
+ }
+ else
+ return;
+ }
+ if ((get_fd = open(tmp_file, O_RDONLY)) == -1)
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ if (input_file)
+ wprintw(com_win, new_file_msg, tmp_file);
+ else
+ wprintw(com_win, cant_open_msg, tmp_file);
+ wrefresh(com_win);
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+ wrefresh(text_win);
+ recv_file = FALSE;
+ input_file = FALSE;
+ return;
+ }
+ else
+ get_file(tmp_file);
+
+ recv_file = FALSE;
+ line_num = curr_line->line_number;
+ scr_vert = tmp_vert;
+ scr_horz = tmp_horz;
+ if (input_file)
+ curr_line= first_line;
+ else
+ curr_line = tmp_line;
+ point = curr_line->line;
+ draw_screen();
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ if (input_file)
+ {
+ wprintw(com_win, open_file_msg, in_file_name, line_num);
+ input_file = FALSE;
+ if (start_at_line != NULL)
+ {
+ line_num = atoi(start_at_line) - 1;
+ move_rel("d", line_num);
+ line_num = 0;
+ start_at_line = NULL;
+ }
+ }
+ else
+ {
+ text_changes = TRUE;
+ if ((tmp_file != NULL) && (*tmp_file != (char) NULL))
+ wprintw(com_win, file_read_fin_msg, tmp_file);
+ }
+ wrefresh(com_win);
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+ wrefresh(text_win);
+}
+
+void
+get_file(file_name) /* read specified file into current buffer */
+char *file_name;
+{
+ int can_read; /* file has at least one character */
+ int length; /* length of line read by read */
+ int append; /* should text be appended to current line */
+ struct text *temp_line;
+
+ if (recv_file) /* if reading a file */
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, reading_file_msg, file_name);
+ if (access(file_name, 2)) /* check permission to write */
+ {
+ if ((errno == ENOTDIR) || (errno == EACCES) || (errno == EROFS) || (errno == ETXTBSY) || (errno == EFAULT))
+ wprintw(com_win, read_only_msg);
+ }
+ wrefresh(com_win);
+ }
+ if (curr_line->line_length > 1) /* if current line is not blank */
+ {
+ insert_line(FALSE);
+ left(FALSE);
+ append = FALSE;
+ }
+ else
+ append = TRUE;
+ can_read = FALSE; /* test if file has any characters */
+ while (((length = read(get_fd, in_string, 512)) != 0) && (length != -1))
+ {
+ can_read = TRUE; /* if set file has at least 1 character */
+ get_line(length, in_string, &append);
+ }
+ if ((can_read) && (curr_line->line_length == 1))
+ {
+ temp_line = curr_line->prev_line;
+ temp_line->next_line = curr_line->next_line;
+ if (temp_line->next_line != NULL)
+ temp_line->next_line->prev_line = temp_line;
+ if (curr_line->line != NULL)
+ free(curr_line->line);
+ free(curr_line);
+ curr_line = temp_line;
+ }
+ if (input_file) /* if this is the file to be edited display number of lines */
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, file_read_lines_msg, in_file_name, curr_line->line_number);
+ wrefresh(com_win);
+ }
+ else if (can_read) /* not input_file and file is non-zero size */
+ text_changes = TRUE;
+
+ if (recv_file) /* if reading a file */
+ {
+ in = EOF;
+ }
+}
+
+void
+get_line(length, in_string, append) /* read string and split into lines */
+int length; /* length of string read by read */
+char *in_string; /* string read by read */
+int *append; /* TRUE if must append more text to end of current line */
+{
+ char *str1;
+ char *str2;
+ int num; /* offset from start of string */
+ int char_count; /* length of new line (or added portion */
+ int temp_counter; /* temporary counter value */
+ struct text *tline; /* temporary pointer to new line */
+ int first_time; /* if TRUE, the first time through the loop */
+
+ str2 = in_string;
+ num = 0;
+ first_time = TRUE;
+ while (num < length)
+ {
+ if (!first_time)
+ {
+ if (num < length)
+ {
+ str2++;
+ num++;
+ }
+ }
+ else
+ first_time = FALSE;
+ str1 = str2;
+ char_count = 1;
+ /* find end of line */
+ while ((*str2 != '\n') && (num < length))
+ {
+ str2++;
+ num++;
+ char_count++;
+ }
+ if (!(*append)) /* if not append to current line, insert new one */
+ {
+ tline = txtalloc(); /* allocate data structure for next line */
+ tline->line_number = curr_line->line_number + 1;
+ tline->next_line = curr_line->next_line;
+ tline->prev_line = curr_line;
+ curr_line->next_line = tline;
+ if (tline->next_line != NULL)
+ tline->next_line->prev_line = tline;
+ curr_line = tline;
+ curr_line->line = point = (char *) malloc(char_count);
+ curr_line->line_length = char_count;
+ curr_line->max_length = char_count;
+ }
+ else
+ {
+ point = resiz_line(char_count, curr_line, curr_line->line_length);
+ curr_line->line_length += (char_count - 1);
+ }
+ for (temp_counter = 1; temp_counter < char_count; temp_counter++)
+ {
+ *point = *str1;
+ point++;
+ str1++;
+ }
+ *point = (char) NULL;
+ *append = FALSE;
+ if ((num == length) && (*str2 != '\n'))
+ *append = TRUE;
+ }
+}
+
+void
+draw_screen() /* redraw the screen from current postion */
+{
+ struct text *temp_line;
+ char *line_out;
+ int temp_vert;
+
+ temp_line = curr_line;
+ temp_vert = scr_vert;
+ wclrtobot(text_win);
+ while ((temp_line != NULL) && (temp_vert <= last_line))
+ {
+ line_out = temp_line->line;
+ draw_line(temp_vert, 0, line_out, 1, temp_line->line_length);
+ temp_vert++;
+ temp_line = temp_line->next_line;
+ }
+ wmove(text_win, temp_vert, 0);
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void
+finish() /* prepare to exit edit session */
+{
+ char *file_name = in_file_name;
+
+ /*
+ | changes made here should be reflected in the 'save'
+ | portion of file_op()
+ */
+
+ if ((file_name == NULL) || (*file_name == (char) NULL))
+ file_name = get_string(save_file_name_prompt, TRUE);
+
+ if ((file_name == NULL) || (*file_name == (char) NULL))
+ {
+ wmove(com_win, 0, 0);
+ wprintw(com_win, file_not_saved_msg);
+ wclrtoeol(com_win);
+ wrefresh(com_win);
+ clear_com_win = TRUE;
+ return;
+ }
+
+ tmp_file = resolve_name(file_name);
+ if (tmp_file != file_name)
+ {
+ free(file_name);
+ file_name = tmp_file;
+ }
+
+ if (write_file(file_name))
+ {
+ text_changes = FALSE;
+ quit(0);
+ }
+}
+
+int
+quit(noverify) /* exit editor */
+int noverify;
+{
+ char *ans;
+
+ touchwin(text_win);
+ wrefresh(text_win);
+ if ((text_changes) && (!noverify))
+ {
+ ans = get_string(changes_made_prompt, TRUE);
+ if (toupper(*ans) == toupper(*yes_char))
+ text_changes = FALSE;
+ else
+ return(0);
+ free(ans);
+ }
+ if (top_of_stack == NULL)
+ {
+ if (info_window)
+ wrefresh(info_win);
+ wrefresh(com_win);
+ resetty();
+ endwin();
+ putchar('\n');
+ exit(0);
+ }
+ else
+ {
+ delete_text();
+ recv_file = TRUE;
+ input_file = TRUE;
+ check_fp();
+ }
+ return(0);
+}
+
+void
+edit_abort(arg)
+int arg;
+{
+ wrefresh(com_win);
+ resetty();
+ endwin();
+ putchar('\n');
+ exit(1);
+}
+
+void
+delete_text()
+{
+ while (curr_line->next_line != NULL)
+ curr_line = curr_line->next_line;
+ while (curr_line != first_line)
+ {
+ free(curr_line->line);
+ curr_line = curr_line->prev_line;
+ free(curr_line->next_line);
+ }
+ curr_line->next_line = NULL;
+ *curr_line->line = (char) NULL;
+ curr_line->line_length = 1;
+ curr_line->line_number = 1;
+ point = curr_line->line;
+ scr_pos = scr_vert = scr_horz = 0;
+ position = 1;
+}
+
+int
+write_file(file_name)
+char *file_name;
+{
+ char cr;
+ char *tmp_point;
+ struct text *out_line;
+ int lines, charac;
+ int temp_pos;
+ int write_flag = TRUE;
+
+ charac = lines = 0;
+ if ((in_file_name == NULL) || strcmp(in_file_name, file_name))
+ {
+ if ((temp_fp = fopen(file_name, "r")))
+ {
+ tmp_point = get_string(file_exists_prompt, TRUE);
+ if (toupper(*tmp_point) == toupper(*yes_char))
+ write_flag = TRUE;
+ else
+ write_flag = FALSE;
+ fclose(temp_fp);
+ free(tmp_point);
+ }
+ }
+
+ clear_com_win = TRUE;
+
+ if (write_flag)
+ {
+ if ((temp_fp = fopen(file_name, "w")) == NULL)
+ {
+ clear_com_win = TRUE;
+ wmove(com_win,0,0);
+ wclrtoeol(com_win);
+ wprintw(com_win, create_file_fail_msg, file_name);
+ wrefresh(com_win);
+ return(FALSE);
+ }
+ else
+ {
+ wmove(com_win,0,0);
+ wclrtoeol(com_win);
+ wprintw(com_win, writing_file_msg, file_name);
+ wrefresh(com_win);
+ cr = '\n';
+ out_line = first_line;
+ while (out_line != NULL)
+ {
+ temp_pos = 1;
+ tmp_point= out_line->line;
+ while (temp_pos < out_line->line_length)
+ {
+ putc(*tmp_point, temp_fp);
+ tmp_point++;
+ temp_pos++;
+ }
+ charac += out_line->line_length;
+ out_line = out_line->next_line;
+ putc(cr, temp_fp);
+ lines++;
+ }
+ fclose(temp_fp);
+ wmove(com_win,0,0);
+ wclrtoeol(com_win);
+ wprintw(com_win, file_written_msg, file_name, lines, charac);
+ wrefresh(com_win);
+ return(TRUE);
+ }
+ }
+ else
+ return(FALSE);
+}
+
+int
+search(display_message) /* search for string in srch_str */
+int display_message;
+{
+ int lines_moved;
+ int iter;
+ int found;
+
+ if ((srch_str == NULL) || (*srch_str == (char) NULL))
+ return(FALSE);
+ if (display_message)
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, searching_msg);
+ wrefresh(com_win);
+ clear_com_win = TRUE;
+ }
+ lines_moved = 0;
+ found = FALSE;
+ srch_line = curr_line;
+ srch_1 = point;
+ if (position < curr_line->line_length)
+ srch_1++;
+ iter = position + 1;
+ while ((!found) && (srch_line != NULL))
+ {
+ while ((iter < srch_line->line_length) && (!found))
+ {
+ srch_2 = srch_1;
+ if (case_sen) /* if case sensitive */
+ {
+ srch_3 = srch_str;
+ while ((*srch_2 == *srch_3) && (*srch_3 != (char) NULL))
+ {
+ found = TRUE;
+ srch_2++;
+ srch_3++;
+ } /* end while */
+ }
+ else /* if not case sensitive */
+ {
+ srch_3 = u_srch_str;
+ while ((toupper(*srch_2) == *srch_3) && (*srch_3 != (char) NULL))
+ {
+ found = TRUE;
+ srch_2++;
+ srch_3++;
+ }
+ } /* end else */
+ if (!((*srch_3 == (char) NULL) && (found)))
+ {
+ found = FALSE;
+ if (iter < srch_line->line_length)
+ srch_1++;
+ iter++;
+ }
+ }
+ if (!found)
+ {
+ srch_line = srch_line->next_line;
+ if (srch_line != NULL)
+ srch_1 = srch_line->line;
+ iter = 1;
+ lines_moved++;
+ }
+ }
+ if (found)
+ {
+ if (display_message)
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wrefresh(com_win);
+ }
+ if (lines_moved == 0)
+ {
+ while (position < iter)
+ right(TRUE);
+ }
+ else
+ {
+ if (lines_moved < 30)
+ {
+ move_rel("d", lines_moved);
+ while (position < iter)
+ right(TRUE);
+ }
+ else
+ {
+ curr_line = srch_line;
+ point = srch_1;
+ position = iter;
+ scanline(point);
+ scr_pos = scr_horz;
+ midscreen((last_line / 2), point);
+ }
+ }
+ }
+ else
+ {
+ if (display_message)
+ {
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, str_not_found_msg, srch_str);
+ wrefresh(com_win);
+ }
+ wmove(text_win, scr_vert,(scr_horz - horiz_offset));
+ }
+ return(found);
+}
+
+void
+search_prompt() /* prompt and read search string (srch_str) */
+{
+ if (srch_str != NULL)
+ free(srch_str);
+ if ((u_srch_str != NULL) && (*u_srch_str != (char) NULL))
+ free(u_srch_str);
+ srch_str = get_string(search_prompt_str, FALSE);
+ gold = FALSE;
+ srch_3 = srch_str;
+ srch_1 = u_srch_str = malloc(strlen(srch_str) + 1);
+ while (*srch_3 != (char) NULL)
+ {
+ *srch_1 = toupper(*srch_3);
+ srch_1++;
+ srch_3++;
+ }
+ *srch_1 = (char) NULL;
+ search(TRUE);
+}
+
+void
+del_char() /* delete current character */
+{
+ in = 8; /* backspace */
+ if (position < curr_line->line_length) /* if not end of line */
+ {
+ position++;
+ point++;
+ scanline(point);
+ delete(TRUE);
+ }
+ else
+ {
+ right(FALSE);
+ delete(FALSE);
+ }
+}
+
+void
+undel_char() /* undelete last deleted character */
+{
+ if (d_char == '\n') /* insert line if last del_char deleted eol */
+ insert_line(TRUE);
+ else
+ {
+ in = d_char;
+ insert(in);
+ }
+}
+
+void
+del_word() /* delete word in front of cursor */
+{
+ int tposit;
+ int difference;
+ char *d_word2;
+ char *d_word3;
+ char tmp_char;
+
+ if (d_word != NULL)
+ free(d_word);
+ d_word = malloc(curr_line->line_length);
+ tmp_char = d_char;
+ d_word3 = point;
+ d_word2 = d_word;
+ tposit = position;
+ while ((tposit < curr_line->line_length) &&
+ ((*d_word3 != ' ') && (*d_word3 != '\t')))
+ {
+ tposit++;
+ *d_word2 = *d_word3;
+ d_word2++;
+ d_word3++;
+ }
+ while ((tposit < curr_line->line_length) &&
+ ((*d_word3 == ' ') || (*d_word3 == '\t')))
+ {
+ tposit++;
+ *d_word2 = *d_word3;
+ d_word2++;
+ d_word3++;
+ }
+ *d_word2 = (char) NULL;
+ d_wrd_len = difference = d_word2 - d_word;
+ d_word2 = point;
+ while (tposit < curr_line->line_length)
+ {
+ tposit++;
+ *d_word2 = *d_word3;
+ d_word2++;
+ d_word3++;
+ }
+ curr_line->line_length -= difference;
+ *d_word2 = (char) NULL;
+ draw_line(scr_vert, scr_horz,point,position,curr_line->line_length);
+ d_char = tmp_char;
+ text_changes = TRUE;
+ formatted = FALSE;
+}
+
+void
+undel_word() /* undelete last deleted word */
+{
+ int temp;
+ int tposit;
+ char *tmp_old_ptr;
+ char *tmp_space;
+ char *tmp_ptr;
+ char *d_word_ptr;
+
+ /*
+ | resize line to handle undeleted word
+ */
+ if ((curr_line->max_length - (curr_line->line_length + d_wrd_len)) < 5)
+ point = resiz_line(d_wrd_len, curr_line, position);
+ tmp_ptr = tmp_space = malloc(curr_line->line_length + d_wrd_len);
+ d_word_ptr = d_word;
+ temp = 1;
+ /*
+ | copy d_word contents into temp space
+ */
+ while (temp <= d_wrd_len)
+ {
+ temp++;
+ *tmp_ptr = *d_word_ptr;
+ tmp_ptr++;
+ d_word_ptr++;
+ }
+ tmp_old_ptr = point;
+ tposit = position;
+ /*
+ | copy contents of line from curent position to eol into
+ | temp space
+ */
+ while (tposit < curr_line->line_length)
+ {
+ temp++;
+ tposit++;
+ *tmp_ptr = *tmp_old_ptr;
+ tmp_ptr++;
+ tmp_old_ptr++;
+ }
+ curr_line->line_length += d_wrd_len;
+ tmp_old_ptr = point;
+ *tmp_ptr = (char) NULL;
+ tmp_ptr = tmp_space;
+ tposit = 1;
+ /*
+ | now copy contents from temp space back to original line
+ */
+ while (tposit < temp)
+ {
+ tposit++;
+ *tmp_old_ptr = *tmp_ptr;
+ tmp_ptr++;
+ tmp_old_ptr++;
+ }
+ *tmp_old_ptr = (char) NULL;
+ free(tmp_space);
+ draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
+}
+
+void
+del_line() /* delete from cursor to end of line */
+{
+ char *dl1;
+ char *dl2;
+ int tposit;
+
+ if (d_line != NULL)
+ free(d_line);
+ d_line = malloc(curr_line->line_length);
+ dl1 = d_line;
+ dl2 = point;
+ tposit = position;
+ while (tposit < curr_line->line_length)
+ {
+ *dl1 = *dl2;
+ dl1++;
+ dl2++;
+ tposit++;
+ }
+ dlt_line->line_length = 1 + tposit - position;
+ *dl1 = (char) NULL;
+ *point = (char) NULL;
+ curr_line->line_length = position;
+ wclrtoeol(text_win);
+ if (curr_line->next_line != NULL)
+ {
+ right(FALSE);
+ delete(FALSE);
+ }
+ text_changes = TRUE;
+}
+
+void
+undel_line() /* undelete last deleted line */
+{
+ char *ud1;
+ char *ud2;
+ int tposit;
+
+ insert_line(TRUE);
+ left(TRUE);
+ point = resiz_line(dlt_line->line_length, curr_line, position);
+ curr_line->line_length += dlt_line->line_length - 1;
+ ud1 = point;
+ ud2 = d_line;
+ tposit = 1;
+ while (tposit < dlt_line->line_length)
+ {
+ tposit++;
+ *ud1 = *ud2;
+ ud1++;
+ ud2++;
+ }
+ *ud1 = (char) NULL;
+ draw_line(scr_vert, scr_horz,point,position,curr_line->line_length);
+}
+
+void
+adv_word() /* advance to next word */
+{
+while ((position < curr_line->line_length) && ((*point != 32) && (*point != 9)))
+ right(TRUE);
+while ((position < curr_line->line_length) && ((*point == 32) || (*point == 9)))
+ right(TRUE);
+}
+
+void
+move_rel(direction, lines) /* move relative to current line */
+char *direction;
+int lines;
+{
+ int i;
+ char *tmp;
+
+ if (*direction == 'u')
+ {
+ scr_pos = 0;
+ while (position > 1)
+ left(TRUE);
+ for (i = 0; i < lines; i++)
+ {
+ up();
+ }
+ if ((last_line > 5) && ( scr_vert < 4))
+ {
+ tmp = point;
+ tmp_line = curr_line;
+ for (i= 0;(i<5)&&(curr_line->prev_line != NULL); i++)
+ {
+ up();
+ }
+ scr_vert = scr_vert + i;
+ curr_line = tmp_line;
+ point = tmp;
+ scanline(point);
+ }
+ }
+ else
+ {
+ if ((position != 1) && (curr_line->next_line != NULL))
+ {
+ nextline();
+ scr_pos = scr_horz = 0;
+ if (horiz_offset)
+ {
+ horiz_offset = 0;
+ midscreen(scr_vert, point);
+ }
+ }
+ else
+ adv_line();
+ for (i = 1; i < lines; i++)
+ {
+ down();
+ }
+ if ((last_line > 10) && (scr_vert > (last_line - 5)))
+ {
+ tmp = point;
+ tmp_line = curr_line;
+ for (i=0; (i<5) && (curr_line->next_line != NULL); i++)
+ {
+ down();
+ }
+ scr_vert = scr_vert - i;
+ curr_line = tmp_line;
+ point = tmp;
+ scanline(point);
+ }
+ }
+ wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void
+eol() /* go to end of line */
+{
+ if (position < curr_line->line_length)
+ {
+ while (position < curr_line->line_length)
+ right(TRUE);
+ }
+ else if (curr_line->next_line != NULL)
+ {
+ right(TRUE);
+ while (position < curr_line->line_length)
+ right(TRUE);
+ }
+}
+
+void
+bol() /* move to beginning of line */
+{
+ if (point != curr_line->line)
+ {
+ while (point != curr_line->line)
+ left(TRUE);
+ }
+ else if (curr_line->prev_line != NULL)
+ {
+ scr_pos = 0;
+ up();
+ }
+}
+
+void
+adv_line() /* advance to beginning of next line */
+{
+ if ((point != curr_line->line) || (scr_pos > 0))
+ {
+ while (position < curr_line->line_length)
+ right(TRUE);
+ right(TRUE);
+ }
+ else if (curr_line->next_line != NULL)
+ {
+ scr_pos = 0;
+ down();
+ }
+}
+
+void
+sh_command(string) /* execute shell command */
+char *string; /* string containing user command */
+{
+ char *temp_point;
+ char *last_slash;
+ char *path; /* directory path to executable */
+ int parent; /* zero if child, child's pid if parent */
+ int value;
+ int return_val;
+ struct text *line_holder;
+
+ if (restrict_mode())
+ {
+ return;
+ }
+
+ if (!(path = getenv("SHELL")))
+ path = "/bin/sh";
+ last_slash = temp_point = path;
+ while (*temp_point != (char) NULL)
+ {
+ if (*temp_point == '/')
+ last_slash = ++temp_point;
+ else
+ temp_point++;
+ }
+
+ /*
+ | if in_pipe is true, then output of the shell operation will be
+ | read by the editor, and curses doesn't need to be turned off
+ */
+
+ if (!in_pipe)
+ {
+ keypad(com_win, FALSE);
+ keypad(text_win, FALSE);
+ echo();
+ nl();
+ noraw();
+ resetty();
+
+#ifndef NCURSE
+ endwin();
+#endif
+ }
+
+ if (in_pipe)
+ {
+ pipe(pipe_in); /* create a pipe */
+ parent = fork();
+ if (!parent) /* if the child */
+ {
+/*
+ | child process which will fork and exec shell command (if shell output is
+ | to be read by editor)
+ */
+ in_pipe = FALSE;
+/*
+ | redirect stdout to pipe
+ */
+ temp_stdout = dup(1);
+ close(1);
+ dup(pipe_in[1]);
+/*
+ | redirect stderr to pipe
+ */
+ temp_stderr = dup(2);
+ close(2);
+ dup(pipe_in[1]);
+ close(pipe_in[1]);
+ /*
+ | child will now continue down 'if (!in_pipe)'
+ | path below
+ */
+ }
+ else /* if the parent */
+ {
+/*
+ | prepare editor to read from the pipe
+ */
+ signal(SIGCHLD, SIG_IGN);
+ line_holder = curr_line;
+ tmp_vert = scr_vert;
+ close(pipe_in[1]);
+ get_fd = pipe_in[0];
+ get_file("");
+ close(pipe_in[0]);
+ scr_vert = tmp_vert;
+ scr_horz = scr_pos = 0;
+ position = 1;
+ curr_line = line_holder;
+ point = curr_line->line;
+ out_pipe = FALSE;
+ signal(SIGCHLD, SIG_DFL);
+/*
+ | since flag "in_pipe" is still TRUE, the path which waits for the child
+ | process to die will be avoided.
+ | (the pipe is closed, no more output can be expected)
+ */
+ }
+ }
+ if (!in_pipe)
+ {
+ signal(SIGINT, SIG_IGN);
+ if (out_pipe)
+ {
+ pipe(pipe_out);
+ }
+/*
+ | fork process which will exec command
+ */
+ parent = fork();
+ if (!parent) /* if the child */
+ {
+ if (shell_fork)
+ putchar('\n');
+ if (out_pipe)
+ {
+/*
+ | prepare the child process (soon to exec a shell command) to read from the
+ | pipe (which will be output from the editor's buffer)
+ */
+ close(0);
+ dup(pipe_out[0]);
+ close(pipe_out[0]);
+ close(pipe_out[1]);
+ }
+ for (value = 1; value < 24; value++)
+ signal(value, SIG_DFL);
+ execl(path, last_slash, "-c", string, NULL);
+ printf(exec_err_msg, path);
+ exit(-1);
+ }
+ else /* if the parent */
+ {
+ if (out_pipe)
+ {
+/*
+ | output the contents of the buffer to the pipe (to be read by the
+ | process forked and exec'd above as stdin)
+ */
+ close(pipe_out[0]);
+ line_holder = first_line;
+ while (line_holder != NULL)
+ {
+ write(pipe_out[1], line_holder->line, (line_holder->line_length-1));
+ write(pipe_out[1], "\n", 1);
+ line_holder = line_holder->next_line;
+ }
+ close(pipe_out[1]);
+ out_pipe = FALSE;
+ }
+ do
+ {
+ return_val = wait((int *) 0);
+ }
+ while ((return_val != parent) && (return_val != -1));
+/*
+ | if this process is actually the child of the editor, exit. Here's how it
+ | works:
+ | The editor forks a process. If output must be sent to the command to be
+ | exec'd another process is forked, and that process (the child's child)
+ | will exec the command. In this case, "shell_fork" will be FALSE. If no
+ | output is to be performed to the shell command, "shell_fork" will be TRUE.
+ | If this is the editor process, shell_fork will be true, otherwise this is
+ | the child of the edit process.
+ */
+ if (!shell_fork)
+ exit(0);
+ }
+ signal(SIGINT, edit_abort);
+ }
+ if (shell_fork)
+ {
+ printf(continue_msg);
+ fflush(stdout);
+ while ((in = getchar()) != '\n')
+ ;
+ }
+
+ if (!in_pipe)
+ {
+ fixterm();
+ noecho();
+ nonl();
+ raw();
+ keypad(text_win, TRUE);
+ keypad(com_win, TRUE);
+ if (info_window)
+ clearok(info_win, TRUE);
+ }
+
+ redraw();
+}
+
+void
+set_up_term() /* set up the terminal for operating with ae */
+{
+ if (!curses_initialized)
+ {
+ initscr();
+ savetty();
+ noecho();
+ raw();
+ nonl();
+ curses_initialized = TRUE;
+ }
+
+ if (((LINES > 15) && (COLS >= 80)) && info_window)
+ last_line = LINES - 8;
+ else
+ {
+ info_window = FALSE;
+ last_line = LINES - 2;
+ }
+
+ idlok(stdscr, TRUE);
+ com_win = newwin(1, COLS, (LINES - 1), 0);
+ keypad(com_win, TRUE);
+ idlok(com_win, TRUE);
+ wrefresh(com_win);
+ if (!info_window)
+ text_win = newwin((LINES - 1), COLS, 0, 0);
+ else
+ text_win = newwin((LINES - 7), COLS, 6, 0);
+ keypad(text_win, TRUE);
+ idlok(text_win, TRUE);
+ wrefresh(text_win);
+ help_win = newwin((LINES - 1), COLS, 0, 0);
+ keypad(help_win, TRUE);
+ idlok(help_win, TRUE);
+ if (info_window)
+ {
+ info_type = CONTROL_KEYS;
+ info_win = newwin(6, COLS, 0, 0);
+ werase(info_win);
+ paint_info_win();
+ }
+
+ last_col = COLS - 1;
+ local_LINES = LINES;
+ local_COLS = COLS;
+}
+
+void
+resize_check()
+{
+ if ((LINES == local_LINES) && (COLS == local_COLS))
+ return;
+
+ if (info_window)
+ delwin(info_win);
+ delwin(text_win);
+ delwin(com_win);
+ delwin(help_win);
+ set_up_term();
+ redraw();
+ wrefresh(text_win);
+}
+
+int
+menu_op(menu_list)
+struct menu_entries * menu_list;
+{
+ WINDOW *temp_win;
+ int max_width, max_height;
+ int x_off, y_off;
+ int counter;
+ int length;
+ int input;
+ int list_size;
+ int top_offset;
+ int temp_int;
+ char *cancel_string = menu_cancel_msg;
+
+ /*
+ | determine number and width of menu items
+ */
+
+ list_size = 1;
+ while (menu_list[list_size + 1].item_string != NULL)
+ list_size++;
+ max_width = strlen(cancel_string);
+ for (counter = 0; counter <= list_size; counter++)
+ {
+ if ((length = strlen(menu_list[counter].item_string)) > max_width)
+ max_width = length;
+ }
+ max_width += 6;
+
+ /*
+ | make sure that window is large enough to handle menu
+ | if not, print error message and return to calling function
+ */
+
+ if ((LINES < list_size) || (max_width > COLS))
+ {
+ wmove(com_win, 0, 0);
+ werase(com_win);
+ wprintw(com_win, menu_size_err_msg);
+ clear_com_win = TRUE;
+ return(0);
+ }
+
+ top_offset = 0;
+ max_height = list_size;
+
+ if (LINES >= (list_size + 8))
+ {
+ max_height = list_size + 8;
+ top_offset = 4;
+ }
+ x_off = (COLS - max_width) / 2;
+ y_off = (LINES - max_height - 1) / 2;
+ temp_win = newwin(max_height, max_width, y_off, x_off);
+ keypad(temp_win, TRUE);
+ werase(temp_win);
+
+ /*
+ | output top and bottom portions of menu box only if window
+ | large enough
+ */
+
+ if (max_height > list_size)
+ {
+ wmove(temp_win, 1, 1);
+ if (!nohighlight)
+ wstandout(temp_win);
+ waddch(temp_win, '+');
+ for (counter = 0; counter < (max_width - 4); counter++)
+ waddch(temp_win, '-');
+ waddch(temp_win, '+');
+
+ wmove(temp_win, (max_height - 2), 1);
+ waddch(temp_win, '+');
+ for (counter = 0; counter < (max_width - 4); counter++)
+ waddch(temp_win, '-');
+ waddch(temp_win, '+');
+ wstandend(temp_win);
+ wmove(temp_win, 2, 3);
+ waddstr(temp_win, menu_list[0].item_string);
+ wmove(temp_win, (max_height - 3), 3);
+ waddstr(temp_win, cancel_string);
+ }
+ if (!nohighlight)
+ wstandout(temp_win);
+ for (counter = 0; counter < (list_size + top_offset); counter++)
+ {
+ if (top_offset == 4)
+ {
+ temp_int = counter + 2;
+ }
+ else
+ temp_int = counter;
+
+ wmove(temp_win, temp_int, 1);
+ waddch(temp_win, '|');
+ wmove(temp_win, temp_int, (max_width - 2));
+ waddch(temp_win, '|');
+ }
+ wstandend(temp_win);
+ for (counter = 1; counter <= list_size; counter++)
+ {
+ wmove(temp_win, (top_offset + counter - 1), 3);
+ waddstr(temp_win, menu_list[counter].item_string);
+ }
+ counter = 1;
+ do
+ {
+ wmove(temp_win, (counter + top_offset - 1), 3);
+ wrefresh(temp_win);
+ input = wgetch(temp_win);
+ if (input == -1)
+ exit(0);
+ switch (input)
+ {
+ case ' ': /* space */
+ case '\022': /* ^r, right */
+ case '\004': /* ^d, down */
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ counter++;
+ if (counter > list_size)
+ counter = 1;
+ break;
+ case '\010': /* ^h, backspace*/
+ case '\014': /* ^l, left */
+ case '\025': /* ^u, up */
+ case 127: /* ^?, delete */
+ case KEY_LEFT:
+ case KEY_UP:
+ counter--;
+ if (counter == 0)
+ counter = list_size;
+ break;
+ case '\033': /* escape key */
+ counter = 0;
+ break;
+ default:
+ break;
+ }
+ }
+ while ((input != '\r') && (input != '\n') && (input != '\033'));
+
+ werase(temp_win);
+ wrefresh(temp_win);
+ delwin(temp_win);
+
+ if ((menu_list[counter].procedure != NULL) ||
+ (menu_list[counter].iprocedure != NULL) ||
+ (menu_list[counter].nprocedure != NULL))
+ {
+ if (menu_list[counter].argument != -1)
+ (*menu_list[counter].iprocedure)(menu_list[counter].argument);
+ else if (menu_list[counter].ptr_argument != NULL)
+ (*menu_list[counter].procedure)(menu_list[counter].ptr_argument);
+ else
+ (*menu_list[counter].nprocedure)();
+ }
+
+ if (info_window)
+ paint_info_win();
+ midscreen(scr_vert, point);
+
+ return(counter);
+}
+
+void
+help()
+{
+ int counter;
+
+ werase(help_win);
+ clearok(help_win, TRUE);
+ for (counter = 0; counter < 22; counter++)
+ {
+ wmove(help_win, counter, 0);
+ waddstr(help_win, (emacs_keys_mode) ?
+ emacs_help_text[counter] : help_text[counter]);
+ }
+ wrefresh(help_win);
+ werase(com_win);
+ wmove(com_win, 0, 0);
+ wprintw(com_win, press_any_key_msg);
+ wrefresh(com_win);
+ counter = wgetch(com_win);
+ if (counter == -1)
+ exit(0);
+ werase(com_win);
+ wmove(com_win, 0, 0);
+ werase(help_win);
+ wrefresh(help_win);
+ wrefresh(com_win);
+ redraw();
+}
+
+void
+paint_info_win()
+{
+ int counter;
+
+ if (!info_window)
+ return;
+
+ werase(info_win);
+ for (counter = 0; counter < 5; counter++)
+ {
+ wmove(info_win, counter, 0);
+ wclrtoeol(info_win);
+ if (info_type == CONTROL_KEYS)
+ waddstr(info_win, (emacs_keys_mode) ?
+ emacs_control_keys[counter] : control_keys[counter]);
+ else if (info_type == COMMANDS)
+ waddstr(info_win, command_strings[counter]);
+ }
+ wmove(info_win, 5, 0);
+ if (!nohighlight)
+ wstandout(info_win);
+ waddstr(info_win, "===============================================================================");
+ wstandend(info_win);
+ wrefresh(info_win);
+}
+
+void
+no_info_window()
+{
+ if (!info_window)
+ return;
+ delwin(info_win);
+ delwin(text_win);
+ info_window = FALSE;
+ last_line = LINES - 2;
+ text_win = newwin((LINES - 1), COLS, 0, 0);
+ keypad(text_win, TRUE);
+ idlok(text_win, TRUE);
+ clearok(text_win, TRUE);
+ midscreen(scr_vert, point);
+ wrefresh(text_win);
+ clear_com_win = TRUE;
+}
+
+void
+create_info_window()
+{
+ if (info_window)
+ return;
+ last_line = LINES - 8;
+ delwin(text_win);
+ text_win = newwin((LINES - 7), COLS, 6, 0);
+ keypad(text_win, TRUE);
+ idlok(text_win, TRUE);
+ werase(text_win);
+ info_window = TRUE;
+ info_win = newwin(6, COLS, 0, 0);
+ werase(info_win);
+ info_type = CONTROL_KEYS;
+ midscreen(min(scr_vert, last_line), point);
+ clearok(info_win, TRUE);
+ paint_info_win();
+ wrefresh(text_win);
+ clear_com_win = TRUE;
+}
+
+int
+file_op(arg)
+int arg;
+{
+ char *string;
+ int flag;
+
+ if (restrict_mode())
+ {
+ return(0);
+ }
+
+ if (arg == READ_FILE)
+ {
+ string = get_string(file_read_prompt_str, TRUE);
+ recv_file = TRUE;
+ tmp_file = resolve_name(string);
+ check_fp();
+ if (tmp_file != string)
+ free(tmp_file);
+ free(string);
+ }
+ else if (arg == WRITE_FILE)
+ {
+ string = get_string(file_write_prompt_str, TRUE);
+ tmp_file = resolve_name(string);
+ write_file(tmp_file);
+ if (tmp_file != string)
+ free(tmp_file);
+ free(string);
+ }
+ else if (arg == SAVE_FILE)
+ {
+ /*
+ | changes made here should be reflected in finish()
+ */
+
+ if (in_file_name)
+ flag = TRUE;
+ else
+ flag = FALSE;
+
+ string = in_file_name;
+ if ((string == NULL) || (*string == (char) NULL))
+ string = get_string(save_file_name_prompt, TRUE);
+ if ((string == NULL) || (*string == (char) NULL))
+ {
+ wmove(com_win, 0, 0);
+ wprintw(com_win, file_not_saved_msg);
+ wclrtoeol(com_win);
+ wrefresh(com_win);
+ clear_com_win = TRUE;
+ return(0);
+ }
+ if (!flag)
+ {
+ tmp_file = resolve_name(string);
+ if (tmp_file != string)
+ {
+ free(string);
+ string = tmp_file;
+ }
+ }
+ if (write_file(string))
+ {
+ in_file_name = string;
+ text_changes = FALSE;
+ }
+ else if (!flag)
+ free(string);
+ }
+ return(0);
+}
+
+void
+shell_op()
+{
+ char *string;
+
+ if (((string = get_string(shell_prompt, TRUE)) != NULL) &&
+ (*string != (char) NULL))
+ {
+ sh_command(string);
+ free(string);
+ }
+}
+
+void
+leave_op()
+{
+ if (text_changes)
+ {
+ menu_op(leave_menu);
+ }
+ else
+ quit(TRUE);
+}
+
+void
+redraw()
+{
+ if (info_window)
+ {
+ clearok(info_win, TRUE);
+ paint_info_win();
+ }
+ else
+ clearok(text_win, TRUE);
+ midscreen(scr_vert, point);
+}
+
+/*
+ | The following routines will "format" a paragraph (as defined by a
+ | block of text with blank lines before and after the block).
+ */
+
+int
+Blank_Line(test_line) /* test if line has any non-space characters */
+struct text *test_line;
+{
+ char *line;
+ int length;
+
+ if (test_line == NULL)
+ return(TRUE);
+
+ length = 1;
+ line = test_line->line;
+
+ /*
+ | To handle troff/nroff documents, consider a line with a
+ | period ('.') in the first column to be blank. To handle mail
+ | messages with included text, consider a line with a '>' blank.
+ */
+
+ if ((*line == '.') || (*line == '>'))
+ return(TRUE);
+
+ while (((*line == ' ') || (*line == '\t')) && (length < test_line->line_length))
+ {
+ length++;
+ line++;
+ }
+ if (length != test_line->line_length)
+ return(FALSE);
+ else
+ return(TRUE);
+}
+
+void
+Format() /* format the paragraph according to set margins */
+{
+ int string_count;
+ int offset;
+ int temp_case;
+ int status;
+ int tmp_af;
+ int counter;
+ char *line;
+ char *tmp_srchstr;
+ char *temp1, *temp2;
+ char *temp_dword;
+ char temp_d_char = d_char;
+
+/*
+ | if observ_margins is not set, or the current line is blank,
+ | do not format the current paragraph
+ */
+
+ if ((!observ_margins) || (Blank_Line(curr_line)))
+ return;
+
+/*
+ | save the currently set flags, and clear them
+ */
+
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, formatting_msg);
+ wrefresh(com_win);
+
+/*
+ | get current position in paragraph, so after formatting, the cursor
+ | will be in the same relative position
+ */
+
+ tmp_af = auto_format;
+ auto_format = FALSE;
+ offset = position;
+ if (position != 1)
+ prev_word();
+ temp_dword = d_word;
+ d_word = NULL;
+ temp_case = case_sen;
+ case_sen = TRUE;
+ tmp_srchstr = srch_str;
+ temp2 = srch_str = (char *) malloc(1 + curr_line->line_length - position);
+ if ((*point == ' ') || (*point == '\t'))
+ adv_word();
+ offset -= position;
+ counter = position;
+ line = temp1 = point;
+ while ((*temp1 != (char) NULL) && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length))
+ {
+ *temp2 = *temp1;
+ temp2++;
+ temp1++;
+ counter++;
+ }
+ *temp2 = (char) NULL;
+ if (position != 1)
+ bol();
+ while (!Blank_Line(curr_line->prev_line))
+ bol();
+ string_count = 0;
+ status = TRUE;
+ while ((line != point) && (status))
+ {
+ status = search(FALSE);
+ string_count++;
+ }
+
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, formatting_msg);
+ wrefresh(com_win);
+
+/*
+ | now get back to the start of the paragraph to start formatting
+ */
+
+ if (position != 1)
+ bol();
+ while (!Blank_Line(curr_line->prev_line))
+ bol();
+
+ observ_margins = FALSE;
+
+/*
+ | Start going through lines, putting spaces at end of lines if they do
+ | not already exist. Append lines together to get one long line, and
+ | eliminate spacing at begin of lines.
+ */
+
+ while (!Blank_Line(curr_line->next_line))
+ {
+ eol();
+ left(TRUE);
+ if (*point != ' ')
+ {
+ right(TRUE);
+ insert(' ');
+ }
+ else
+ right(TRUE);
+ del_char();
+ if ((*point == ' ') || (*point == '\t'))
+ del_word();
+ }
+
+/*
+ | Now there is one long line. Eliminate extra spaces within the line
+ | after the first word (so as not to blow away any indenting the user
+ | may have put in).
+ */
+
+ bol();
+ adv_word();
+ while (position < curr_line->line_length)
+ {
+ if ((*point == ' ') && (*(point + 1) == ' '))
+ del_char();
+ else
+ right(TRUE);
+ }
+
+/*
+ | Now make sure there are two spaces after a '.'.
+ */
+
+ bol();
+ while (position < curr_line->line_length)
+ {
+ if ((*point == '.') && (*(point + 1) == ' '))
+ {
+ right(TRUE);
+ insert(' ');
+ insert(' ');
+ while (*point == ' ')
+ del_char();
+ }
+ right(TRUE);
+ }
+
+ observ_margins = TRUE;
+ bol();
+
+ wmove(com_win, 0, 0);
+ wclrtoeol(com_win);
+ wprintw(com_win, formatting_msg);
+ wrefresh(com_win);
+
+/*
+ | create lines between margins
+ */
+
+ while (position < curr_line->line_length)
+ {
+ while ((scr_pos < right_margin) && (position < curr_line->line_length))
+ right(TRUE);
+ if (position < curr_line->line_length)
+ {
+ prev_word();
+ if (position == 1)
+ adv_word();
+ insert_line(TRUE);
+ }
+ }
+
+/*
+ | go back to begin of paragraph, put cursor back to original position
+ */
+
+ bol();
+ while (!Blank_Line(curr_line->prev_line))
+ bol();
+
+/*
+ | find word cursor was in
+ */
+
+ while ((status) && (string_count > 0))
+ {
+ search(FALSE);
+ string_count--;
+ }
+
+/*
+ | offset the cursor to where it was before from the start of the word
+ */
+
+ while (offset > 0)
+ {
+ offset--;
+ right(TRUE);
+ }
+
+/*
+ | reset flags and strings to what they were before formatting
+ */
+
+ if (d_word != NULL)
+ free(d_word);
+ d_word = temp_dword;
+ case_sen = temp_case;
+ free(srch_str);
+ srch_str = tmp_srchstr;
+ d_char = temp_d_char;
+ auto_format = tmp_af;
+
+ midscreen(scr_vert, point);
+ werase(com_win);
+ wrefresh(com_win);
+}
+
+char *init_name[3] = {
+ "/usr/share/misc/init.ee",
+ NULL,
+ ".init.ee"
+ };
+
+void
+ee_init() /* check for init file and read it if it exists */
+{
+ FILE *init_file;
+ char *string;
+ char *str1;
+ char *str2;
+ char *home;
+ int counter;
+ int temp_int;
+
+ string = getenv("HOME");
+ str1 = home = malloc(strlen(string)+10);
+ strcpy(home, string);
+ strcat(home, "/.init.ee");
+ init_name[1] = home;
+ string = malloc(512);
+
+ for (counter = 0; counter < 3; counter++)
+ {
+ if (!(access(init_name[counter], 4)))
+ {
+ init_file = fopen(init_name[counter], "r");
+ while ((str2 = fgets(string, 512, init_file)) != NULL)
+ {
+ if (unique_test(string, init_strings) != 1)
+ continue;
+ str1 = str2 = string;
+ while (*str2 != '\n')
+ str2++;
+ *str2 = (char) NULL;
+ if (compare(str1, CASE, FALSE))
+ case_sen = TRUE;
+ else if (compare(str1, NOCASE, FALSE))
+ case_sen = FALSE;
+ else if (compare(str1, EXPAND, FALSE))
+ expand_tabs = TRUE;
+ else if (compare(str1, NOEXPAND, FALSE))
+ expand_tabs = FALSE;
+ else if (compare(str1, INFO, FALSE))
+ info_window = TRUE;
+ else if (compare(str1, NOINFO, FALSE))
+ info_window = FALSE;
+ else if (compare(str1, MARGINS, FALSE))
+ observ_margins = TRUE;
+ else if (compare(str1, NOMARGINS, FALSE))
+ observ_margins = FALSE;
+ else if (compare(str1, AUTOFORMAT, FALSE))
+ {
+ auto_format = TRUE;
+ observ_margins = TRUE;
+ }
+ else if (compare(str1, NOAUTOFORMAT, FALSE))
+ auto_format = FALSE;
+ else if (compare(str1, Echo, FALSE))
+ {
+ str1 = next_word(str1);
+ if (*str1 != (char) NULL)
+ echo_string(str1);
+ }
+ else if (compare(str1, PRINTCOMMAND, FALSE))
+ {
+ str1 = next_word(str1);
+ print_command = malloc(strlen(str1)+1);
+ strcpy(print_command, str1);
+ }
+ else if (compare(str1, RIGHTMARGIN, FALSE))
+ {
+ str1 = next_word(str1);
+ if ((*str1 >= '0') && (*str1 <= '9'))
+ {
+ temp_int = atoi(str1);
+ if (temp_int > 0)
+ right_margin = temp_int;
+ }
+ }
+ else if (compare(str1, HIGHLIGHT, FALSE))
+ nohighlight = FALSE;
+ else if (compare(str1, NOHIGHLIGHT, FALSE))
+ nohighlight = TRUE;
+ else if (compare(str1, EIGHTBIT, FALSE))
+ eightbit = TRUE;
+ else if (compare(str1, NOEIGHTBIT, FALSE))
+ eightbit = FALSE;
+ else if (compare(str1, EMACS_string, FALSE))
+ emacs_keys_mode = TRUE;
+ else if (compare(str1, NOEMACS_string, FALSE))
+ emacs_keys_mode = FALSE;
+ }
+ fclose(init_file);
+ }
+ }
+ free(string);
+ free(home);
+}
+
+void
+echo_string(string) /* echo the given string */
+char *string;
+{
+ char *temp;
+ int Counter;
+
+ temp = string;
+ while (*temp != (char) NULL)
+ {
+ if (*temp == '\\')
+ {
+ temp++;
+ if (*temp == 'n')
+ putchar('\n');
+ else if (*temp == 't')
+ putchar('\t');
+ else if (*temp == 'b')
+ putchar('\b');
+ else if (*temp == 'r')
+ putchar('\r');
+ else if (*temp == 'f')
+ putchar('\f');
+ else if ((*temp == 'e') || (*temp == 'E'))
+ putchar('\033'); /* escape */
+ else if (*temp == '\\')
+ putchar('\\');
+ else if (*temp == '\'')
+ putchar('\'');
+ else if ((*temp >= '0') && (*temp <= '9'))
+ {
+ Counter = 0;
+ while ((*temp >= '0') && (*temp <= '9'))
+ {
+ Counter = (8 * Counter) + (*temp - '0');
+ temp++;
+ }
+ putchar(Counter);
+ temp--;
+ }
+ temp++;
+ }
+ else
+ {
+ putchar(*temp);
+ temp++;
+ }
+ }
+
+ fflush(stdout);
+}
+
+void
+spell_op() /* check spelling of words in the editor */
+{
+ if (restrict_mode())
+ {
+ return;
+ }
+ top(); /* go to top of file */
+ insert_line(FALSE); /* create two blank lines */
+ insert_line(FALSE);
+ top();
+ command(shell_echo_msg);
+ adv_line();
+ wmove(com_win, 0, 0);
+ wprintw(com_win, spell_in_prog_msg);
+ wrefresh(com_win);
+ command("<>!spell"); /* send contents of buffer to command 'spell'
+ and read the results back into the editor */
+}
+
+void
+ispell_op()
+{
+ char name[128];
+ char string[256];
+ int pid;
+
+ if (restrict_mode())
+ {
+ return;
+ }
+ pid = getpid();
+ sprintf(name, "/tmp/ee.%d", pid);
+ if (write_file(name))
+ {
+ sprintf(string, "ispell %s", name);
+ sh_command(string);
+ delete_text();
+ tmp_file = name;
+ recv_file = TRUE;
+ check_fp();
+ unlink(name);
+ }
+}
+
+int
+first_word_len(test_line)
+struct text *test_line;
+{
+ int counter;
+ char *pnt;
+
+ pnt = test_line->line;
+ if ((test_line == NULL) || (pnt == NULL) || (*pnt == (char) NULL) ||
+ (*pnt == '.') || (*pnt == '>'))
+ return(0);
+
+ if ((*pnt == ' ') || (*pnt == '\t'))
+ {
+ pnt = next_word(pnt);
+ }
+
+ if (*pnt == (char) NULL)
+ return(0);
+
+ counter = 0;
+ while ((*pnt != (char) NULL) && ((*pnt != ' ') && (*pnt != '\t')))
+ {
+ pnt++;
+ counter++;
+ }
+ while ((*pnt != (char) NULL) && ((*pnt == ' ') || (*pnt == '\t')))
+ {
+ pnt++;
+ counter++;
+ }
+ return(counter);
+}
+
+void
+Auto_Format() /* format the paragraph according to set margins */
+{
+ int string_count;
+ int offset;
+ int temp_case;
+ int word_len;
+ int temp_dwl;
+ int tmp_d_line_length;
+ int leave_loop = FALSE;
+ int status;
+ int counter;
+ char *line;
+ char *tmp_srchstr;
+ char *temp1, *temp2;
+ char *temp_dword;
+ char temp_d_char = d_char;
+ char *tmp_d_line;
+
+/*
+ | if observ_margins is not set, or the current line is blank,
+ | do not format the current paragraph
+ */
+
+ if ((!observ_margins) || (Blank_Line(curr_line)))
+ return;
+
+/*
+ | get current position in paragraph, so after formatting, the cursor
+ | will be in the same relative position
+ */
+
+ tmp_d_line = d_line;
+ tmp_d_line_length = dlt_line->line_length;
+ d_line = NULL;
+ auto_format = FALSE;
+ offset = position;
+ if ((position != 1) && ((*point == ' ') || (*point == '\t') || (position == curr_line->line_length) || (*point == (char) NULL)))
+ prev_word();
+ temp_dword = d_word;
+ temp_dwl = d_wrd_len;
+ d_wrd_len = 0;
+ d_word = NULL;
+ temp_case = case_sen;
+ case_sen = TRUE;
+ tmp_srchstr = srch_str;
+ temp2 = srch_str = (char *) malloc(1 + curr_line->line_length - position);
+ if ((*point == ' ') || (*point == '\t'))
+ adv_word();
+ offset -= position;
+ counter = position;
+ line = temp1 = point;
+ while ((*temp1 != (char) NULL) && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length))
+ {
+ *temp2 = *temp1;
+ temp2++;
+ temp1++;
+ counter++;
+ }
+ *temp2 = (char) NULL;
+ if (position != 1)
+ bol();
+ while (!Blank_Line(curr_line->prev_line))
+ bol();
+ string_count = 0;
+ status = TRUE;
+ while ((line != point) && (status))
+ {
+ status = search(FALSE);
+ string_count++;
+ }
+
+/*
+ | now get back to the start of the paragraph to start checking
+ */
+
+ if (position != 1)
+ bol();
+ while (!Blank_Line(curr_line->prev_line))
+ bol();
+
+/*
+ | Start going through lines, putting spaces at end of lines if they do
+ | not already exist. Check line length, and move words to the next line
+ | if they cross the margin. Then get words from the next line if they
+ | will fit in before the margin.
+ */
+
+ while (!leave_loop)
+ {
+ if (position != curr_line->line_length)
+ eol();
+ left(TRUE);
+ if (*point != ' ')
+ {
+ right(TRUE);
+ insert(' ');
+ }
+ else
+ right(TRUE);
+
+ /*
+ | fill line if first word on next line will fit
+ | in the line without crossing the margin
+ */
+
+ while ((curr_line->next_line != NULL) &&
+ ((word_len = first_word_len(curr_line->next_line)) > 0)
+ && ((scr_pos + word_len) < right_margin))
+ {
+ adv_line();
+ if ((*point == ' ') || (*point == '\t'))
+ adv_word();
+ del_word();
+ if (position != 1)
+ bol();
+ if (Blank_Line(curr_line))
+ {
+ del_line();
+ }
+ /*
+ | go to end of previous line
+ */
+ left(TRUE);
+ undel_word();
+ eol();
+ /*
+ | make sure there's a space at the end of the line
+ */
+ left(TRUE);
+ if (*point != ' ')
+ {
+ right(TRUE);
+ insert(' ');
+ }
+ else
+ right(TRUE);
+ }
+
+ /*
+ | make sure line does not cross right margin
+ */
+
+ while (right_margin <= scr_pos)
+ {
+ prev_word();
+ if (position != 1)
+ {
+ del_word();
+ if (Blank_Line(curr_line->next_line))
+ insert_line(TRUE);
+ else
+ adv_line();
+ if ((*point == ' ') || (*point == '\t'))
+ adv_word();
+ undel_word();
+ if (position != 1)
+ bol();
+ left(TRUE);
+ }
+ }
+
+ if (!Blank_Line(curr_line->next_line))
+ adv_line();
+ else
+ leave_loop = TRUE;
+ }
+
+/*
+ | go back to begin of paragraph, put cursor back to original position
+ */
+
+ bol();
+ while (!Blank_Line(curr_line->prev_line))
+ bol();
+
+/*
+ | find word cursor was in
+ */
+
+ status = TRUE;
+ while ((status) && (string_count > 0))
+ {
+ status = search(FALSE);
+ string_count--;
+ }
+
+/*
+ | offset the cursor to where it was before from the start of the word
+ */
+
+ while (offset > 0)
+ {
+ offset--;
+ right(TRUE);
+ }
+
+ if ((string_count > 0) && (offset < 0))
+ {
+ while (offset < 0)
+ {
+ offset++;
+ left(TRUE);
+ }
+ }
+
+/*
+ | reset flags and strings to what they were before formatting
+ */
+
+ if (d_word != NULL)
+ free(d_word);
+ d_word = temp_dword;
+ d_wrd_len = temp_dwl;
+ case_sen = temp_case;
+ free(srch_str);
+ srch_str = tmp_srchstr;
+ d_char = temp_d_char;
+ auto_format = TRUE;
+ dlt_line->line_length = tmp_d_line_length;
+ d_line = tmp_d_line;
+
+ formatted = TRUE;
+ midscreen(scr_vert, point);
+}
+
+void
+modes_op()
+{
+ int ret_value;
+ int counter;
+ char *string;
+
+ do
+ {
+ sprintf(modes_menu[1].item_string, "%s %s", mode_strings[1],
+ (expand_tabs ? ON : OFF));
+ sprintf(modes_menu[2].item_string, "%s %s", mode_strings[2],
+ (case_sen ? ON : OFF));
+ sprintf(modes_menu[3].item_string, "%s %s", mode_strings[3],
+ (observ_margins ? ON : OFF));
+ sprintf(modes_menu[4].item_string, "%s %s", mode_strings[4],
+ (auto_format ? ON : OFF));
+ sprintf(modes_menu[5].item_string, "%s %s", mode_strings[5],
+ (eightbit ? ON : OFF));
+ sprintf(modes_menu[6].item_string, "%s %s", mode_strings[6],
+ (info_window ? ON : OFF));
+ sprintf(modes_menu[7].item_string, "%s %s", mode_strings[7],
+ (emacs_keys_mode ? ON : OFF));
+ sprintf(modes_menu[8].item_string, "%s %d", mode_strings[8],
+ right_margin);
+
+ ret_value = menu_op(modes_menu);
+
+ switch (ret_value)
+ {
+ case 1:
+ expand_tabs = !expand_tabs;
+ break;
+ case 2:
+ case_sen = !case_sen;
+ break;
+ case 3:
+ observ_margins = !observ_margins;
+ break;
+ case 4:
+ auto_format = !auto_format;
+ if (auto_format)
+ observ_margins = TRUE;
+ break;
+ case 5:
+ eightbit = !eightbit;
+ redraw();
+ wnoutrefresh(text_win);
+ break;
+ case 6:
+ if (info_window)
+ no_info_window();
+ else
+ create_info_window();
+ break;
+ case 7:
+ emacs_keys_mode = !emacs_keys_mode;
+ if (info_window)
+ paint_info_win();
+ break;
+ case 8:
+ string = get_string(margin_prompt, TRUE);
+ if (string != NULL)
+ {
+ counter = atoi(string);
+ if (counter > 0)
+ right_margin = counter;
+ free(string);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while (ret_value != 0);
+}
+
+char *
+is_in_string(string, substring) /* a strstr() look-alike for systems without
+ strstr() */
+char * string, *substring;
+{
+ char *full, *sub;
+
+ for (sub = substring; (sub != NULL) && (*sub != (char)NULL); sub++)
+ {
+ for (full = string; (full != NULL) && (*full != (char)NULL);
+ full++)
+ {
+ if (*sub == *full)
+ return(full);
+ }
+ }
+ return(NULL);
+}
+
+/*
+ | handle names of the form "~/file", "~user/file",
+ | "$HOME/foo", "~/$FOO", etc.
+ */
+
+char *
+resolve_name(name)
+char *name;
+{
+ char long_buffer[1024];
+ char short_buffer[128];
+ char *buffer;
+ char *slash;
+ char *tmp;
+ char *start_of_var;
+ int offset;
+ int index;
+ int counter;
+ struct passwd *user;
+
+ if (name[0] == '~')
+ {
+ if (name[1] == '/')
+ {
+ index = getuid();
+ user = (struct passwd *) getpwuid(index);
+ slash = name + 1;
+ }
+ else
+ {
+ slash = strchr(name, '/');
+ if (slash == NULL)
+ return(name);
+ *slash = (char) NULL;
+ user = (struct passwd *) getpwnam((name + 1));
+ *slash = '/';
+ }
+ if (user == NULL)
+ {
+ return(name);
+ }
+ buffer = malloc(strlen(user->pw_dir) + strlen(slash) + 1);
+ strcpy(buffer, user->pw_dir);
+ strcat(buffer, slash);
+ }
+ else
+ buffer = name;
+
+ if (is_in_string(buffer, "$"))
+ {
+ tmp = buffer;
+ index = 0;
+
+ while ((*tmp != (char) NULL) && (index < 1024))
+ {
+
+ while ((*tmp != (char) NULL) && (*tmp != '$') &&
+ (index < 1024))
+ {
+ long_buffer[index] = *tmp;
+ tmp++;
+ index++;
+ }
+
+ if ((*tmp == '$') && (index < 1024))
+ {
+ counter = 0;
+ start_of_var = tmp;
+ tmp++;
+ if (*tmp == '{') /* } */ /* bracketed variable name */
+ {
+ tmp++; /* { */
+ while ((*tmp != (char) NULL) &&
+ (*tmp != '}') &&
+ (counter < 128))
+ {
+ short_buffer[counter] = *tmp;
+ counter++;
+ tmp++;
+ } /* { */
+ if (*tmp == '}')
+ tmp++;
+ }
+ else
+ {
+ while ((*tmp != (char) NULL) &&
+ (*tmp != '/') &&
+ (*tmp != '$') &&
+ (counter < 128))
+ {
+ short_buffer[counter] = *tmp;
+ counter++;
+ tmp++;
+ }
+ }
+ short_buffer[counter] = (char) NULL;
+ if ((slash = getenv(short_buffer)) != NULL)
+ {
+ offset = strlen(slash);
+ if ((offset + index) < 1024)
+ strcpy(&long_buffer[index], slash);
+ index += offset;
+ }
+ else
+ {
+ while ((start_of_var != tmp) && (index < 1024))
+ {
+ long_buffer[index] = *start_of_var;
+ start_of_var++;
+ index++;
+ }
+ }
+ }
+ }
+
+ if (index == 1024)
+ return(buffer);
+ else
+ long_buffer[index] = (char) NULL;
+
+ if (name != buffer)
+ free(buffer);
+ buffer = malloc(index + 1);
+ strcpy(buffer, long_buffer);
+ }
+
+ return(buffer);
+}
+
+int
+restrict_mode()
+{
+ if (!restricted)
+ return(FALSE);
+
+ wmove(com_win, 0, 0);
+ wprintw(com_win, restricted_msg);
+ wclrtoeol(com_win);
+ wrefresh(com_win);
+ clear_com_win = TRUE;
+ return(TRUE);
+}
+
+/*
+ | The following routine tests the input string against the list of
+ | strings, to determine if the string is a unique match with one of the
+ | valid values.
+ */
+
+int
+unique_test(string, list)
+char *string;
+char *list[];
+{
+ int counter;
+ int num_match;
+ int result;
+
+ num_match = 0;
+ counter = 0;
+ while (list[counter] != NULL)
+ {
+ result = compare(string, list[counter], FALSE);
+ if (result)
+ num_match++;
+ counter++;
+ }
+ return(num_match);
+}
+
+#ifndef NO_CATGETS
+/*
+ | Get the catalog entry, and if it got it from the catalog,
+ | make a copy, since the buffer will be overwritten by the
+ | next call to catgets().
+ */
+
+char *
+catgetlocal(number, string)
+int number;
+char *string;
+{
+ char *temp1;
+ char *temp2;
+
+ temp1 = catgets(catalog, 1, number, string);
+ if (temp1 != string)
+ {
+ temp2 = malloc(strlen(temp1) + 1);
+ strcpy(temp2, temp1);
+ temp1 = temp2;
+ }
+ return(temp1);
+}
+#endif /* NO_CATGETS */
+
+/*
+ | The following is to allow for using message catalogs which allow
+ | the software to be 'localized', that is, to use different languages
+ | all with the same binary. For more information, see your system
+ | documentation, or the X/Open Internationalization Guide.
+ */
+
+void
+strings_init()
+{
+ int counter;
+
+#ifndef NO_CATGETS
+ setlocale(LC_ALL, "");
+ catalog = catopen("ee", 0);
+#endif /* NO_CATGETS */
+
+ modes_menu[0].item_string = catgetlocal( 1, "modes menu");
+ mode_strings[1] = catgetlocal( 2, "tabs to spaces ");
+ mode_strings[2] = catgetlocal( 3, "case sensitive search");
+ mode_strings[3] = catgetlocal( 4, "margins observed ");
+ mode_strings[4] = catgetlocal( 5, "auto-paragraph format");
+ mode_strings[5] = catgetlocal( 6, "eightbit characters ");
+ mode_strings[6] = catgetlocal( 7, "info window ");
+ mode_strings[8] = catgetlocal( 8, "right margin ");
+ leave_menu[0].item_string = catgetlocal( 9, "leave menu");
+ leave_menu[1].item_string = catgetlocal( 10, "save changes");
+ leave_menu[2].item_string = catgetlocal( 11, "no save");
+ file_menu[0].item_string = catgetlocal( 12, "file menu");
+ file_menu[1].item_string = catgetlocal( 13, "read a file");
+ file_menu[2].item_string = catgetlocal( 14, "write a file");
+ file_menu[3].item_string = catgetlocal( 15, "save file");
+ file_menu[4].item_string = catgetlocal( 16, "print editor contents");
+ search_menu[0].item_string = catgetlocal( 17, "search menu");
+ search_menu[1].item_string = catgetlocal( 18, "search for ...");
+ search_menu[2].item_string = catgetlocal( 19, "search");
+ spell_menu[0].item_string = catgetlocal( 20, "spell menu");
+ spell_menu[1].item_string = catgetlocal( 21, "use 'spell'");
+ spell_menu[2].item_string = catgetlocal( 22, "use 'ispell'");
+ misc_menu[0].item_string = catgetlocal( 23, "miscellaneous menu");
+ misc_menu[1].item_string = catgetlocal( 24, "format paragraph");
+ misc_menu[2].item_string = catgetlocal( 25, "shell command");
+ misc_menu[3].item_string = catgetlocal( 26, "check spelling");
+ main_menu[0].item_string = catgetlocal( 27, "main menu");
+ main_menu[1].item_string = catgetlocal( 28, "leave editor");
+ main_menu[2].item_string = catgetlocal( 29, "help");
+ main_menu[3].item_string = catgetlocal( 30, "file operations");
+ main_menu[4].item_string = catgetlocal( 31, "redraw screen");
+ main_menu[5].item_string = catgetlocal( 32, "settings");
+ main_menu[6].item_string = catgetlocal( 33, "search");
+ main_menu[7].item_string = catgetlocal( 34, "miscellaneous");
+ help_text[0] = catgetlocal( 35, "Control keys: ");
+ help_text[1] = catgetlocal( 36, "^a ascii code ^i tab ^r right ");
+ help_text[2] = catgetlocal( 37, "^b bottom of text ^j newline ^t top of text ");
+ help_text[3] = catgetlocal( 38, "^c command ^k delete char ^u up ");
+ help_text[4] = catgetlocal( 39, "^d down ^l left ^v undelete word ");
+ help_text[5] = catgetlocal( 40, "^e search prompt ^m newline ^w delete word ");
+ help_text[6] = catgetlocal( 41, "^f undelete char ^n next page ^x search ");
+ help_text[7] = catgetlocal( 42, "^g begin of line ^o end of line ^y delete line ");
+ help_text[8] = catgetlocal( 43, "^h backspace ^p prev page ^z undelete line ");
+ help_text[9] = catgetlocal( 44, "^[ (escape) menu ");
+ help_text[10] = catgetlocal( 45, " ");
+ help_text[11] = catgetlocal( 46, "Commands: ");
+ help_text[12] = catgetlocal( 47, "help : get this info file : print file name ");
+ help_text[13] = catgetlocal( 48, "read : read a file char : ascii code of char ");
+ help_text[14] = catgetlocal( 49, "write : write a file case : case sensitive search ");
+ help_text[15] = catgetlocal( 50, "exit : leave and save nocase : case insensitive search ");
+ help_text[16] = catgetlocal( 51, "quit : leave, no save !cmd : execute \"cmd\" in shell ");
+ help_text[17] = catgetlocal( 52, "line : display line # 0-9 : go to line \"#\" ");
+ help_text[18] = catgetlocal( 53, "expand : expand tabs noexpand: do not expand tabs ");
+ help_text[19] = catgetlocal( 54, " ");
+ help_text[20] = catgetlocal( 55, " ee [-i] [-e] [-h] [file(s)] ");
+ help_text[21] = catgetlocal( 56, " -i : no information window -e : do not expand tabs -h : no highlight ");
+ control_keys[0] = catgetlocal( 57, "^[ (escape) menu ^e search prompt ^y delete line ^u up ^p prev page ");
+ control_keys[1] = catgetlocal( 58, "^a ascii code ^x search ^z undelete line ^d down ^n next page ");
+ control_keys[2] = catgetlocal( 59, "^b bottom of text ^g begin of line ^w delete word ^l left ");
+ control_keys[3] = catgetlocal( 60, "^t top of text ^o end of line ^v undelete word ^r right ");
+ control_keys[4] = catgetlocal( 61, "^c command ^k delete char ^f undelete char ");
+ command_strings[0] = catgetlocal( 62, "help : get help info |file : print file name |line : print line # ");
+ command_strings[1] = catgetlocal( 63, "read : read a file |char : ascii code of char |0-9 : go to line \"#\"");
+ command_strings[2] = catgetlocal( 64, "write: write a file |case : case sensitive search |exit : leave and save ");
+ command_strings[3] = catgetlocal( 65, "!cmd : shell \"cmd\" |nocase: ignore case in search |quit : leave, no save");
+ command_strings[4] = catgetlocal( 66, "expand: expand tabs |noexpand: do not expand tabs ");
+ com_win_message = catgetlocal( 67, " press Escape (^[) for menu");
+ no_file_string = catgetlocal( 68, "no file");
+ ascii_code_str = catgetlocal( 69, "ascii code: ");
+ printer_msg_str = catgetlocal( 70, "sending contents of buffer to \"%s\" ");
+ command_str = catgetlocal( 71, "command: ");
+ file_write_prompt_str = catgetlocal( 72, "name of file to write: ");
+ file_read_prompt_str = catgetlocal( 73, "name of file to read: ");
+ char_str = catgetlocal( 74, "character = %d");
+ unkn_cmd_str = catgetlocal( 75, "unknown command \"%s\"");
+ non_unique_cmd_msg = catgetlocal( 76, "entered command is not unique");
+ line_num_str = catgetlocal( 77, "line %d ");
+ line_len_str = catgetlocal( 78, "length = %d");
+ current_file_str = catgetlocal( 79, "current file is \"%s\" ");
+ usage0 = catgetlocal( 80, "usage: %s [-i] [-e] [-h] [+line_number] [file(s)]\n");
+ usage1 = catgetlocal( 81, " -i turn off info window\n");
+ usage2 = catgetlocal( 82, " -e do not convert tabs to spaces\n");
+ usage3 = catgetlocal( 83, " -h do not use highlighting\n");
+ file_is_dir_msg = catgetlocal( 84, "file \"%s\" is a directory");
+ new_file_msg = catgetlocal( 85, "new file \"%s\"");
+ cant_open_msg = catgetlocal( 86, "can't open \"%s\"");
+ open_file_msg = catgetlocal( 87, "file \"%s\", %d lines");
+ file_read_fin_msg = catgetlocal( 88, "finished reading file \"%s\"");
+ reading_file_msg = catgetlocal( 89, "reading file \"%s\"");
+ read_only_msg = catgetlocal( 90, ", read only");
+ file_read_lines_msg = catgetlocal( 91, "file \"%s\", %d lines");
+ save_file_name_prompt = catgetlocal( 92, "enter name of file: ");
+ file_not_saved_msg = catgetlocal( 93, "no filename entered: file not saved");
+ changes_made_prompt = catgetlocal( 94, "changes have been made, are you sure? (y/n [n]) ");
+ yes_char = catgetlocal( 95, "y");
+ file_exists_prompt = catgetlocal( 96, "file already exists, overwrite? (y/n) [n] ");
+ create_file_fail_msg = catgetlocal( 97, "unable to create file \"%s\"");
+ writing_file_msg = catgetlocal( 98, "writing file \"%s\"");
+ file_written_msg = catgetlocal( 99, "\"%s\" %d lines, %d characters");
+ searching_msg = catgetlocal( 100, " ...searching");
+ str_not_found_msg = catgetlocal( 101, "string \"%s\" not found");
+ search_prompt_str = catgetlocal( 102, "search for: ");
+ exec_err_msg = catgetlocal( 103, "could not exec %s\n");
+ continue_msg = catgetlocal( 104, "press return to continue ");
+ menu_cancel_msg = catgetlocal( 105, "press Esc to cancel");
+ menu_size_err_msg = catgetlocal( 106, "menu too large for window");
+ press_any_key_msg = catgetlocal( 107, "press any key to continue ");
+ shell_prompt = catgetlocal( 108, "shell command: ");
+ formatting_msg = catgetlocal( 109, "...formatting paragraph...");
+ shell_echo_msg = catgetlocal( 110, "<!echo 'list of unrecognized words'; echo -=-=-=-=-=-");
+ spell_in_prog_msg = catgetlocal( 111, "sending contents of edit buffer to 'spell'");
+ margin_prompt = catgetlocal( 112, "right margin is: ");
+ restricted_msg = catgetlocal( 113, "restricted mode: unable to perform requested operation");
+ ON = catgetlocal( 114, "ON");
+ OFF = catgetlocal( 115, "OFF");
+ HELP = catgetlocal( 116, "HELP");
+ WRITE = catgetlocal( 117, "WRITE");
+ READ = catgetlocal( 118, "READ");
+ LINE = catgetlocal( 119, "LINE");
+ FILE_str = catgetlocal( 120, "FILE");
+ CHARACTER = catgetlocal( 121, "CHARACTER");
+ REDRAW = catgetlocal( 122, "REDRAW");
+ RESEQUENCE = catgetlocal( 123, "RESEQUENCE");
+ AUTHOR = catgetlocal( 124, "AUTHOR");
+ VERSION = catgetlocal( 125, "VERSION");
+ CASE = catgetlocal( 126, "CASE");
+ NOCASE = catgetlocal( 127, "NOCASE");
+ EXPAND = catgetlocal( 128, "EXPAND");
+ NOEXPAND = catgetlocal( 129, "NOEXPAND");
+ Exit_string = catgetlocal( 130, "EXIT");
+ QUIT_string = catgetlocal( 131, "QUIT");
+ INFO = catgetlocal( 132, "INFO");
+ NOINFO = catgetlocal( 133, "NOINFO");
+ MARGINS = catgetlocal( 134, "MARGINS");
+ NOMARGINS = catgetlocal( 135, "NOMARGINS");
+ AUTOFORMAT = catgetlocal( 136, "AUTOFORMAT");
+ NOAUTOFORMAT = catgetlocal( 137, "NOAUTOFORMAT");
+ Echo = catgetlocal( 138, "ECHO");
+ PRINTCOMMAND = catgetlocal( 139, "PRINTCOMMAND");
+ RIGHTMARGIN = catgetlocal( 140, "RIGHTMARGIN");
+ HIGHLIGHT = catgetlocal( 141, "HIGHLIGHT");
+ NOHIGHLIGHT = catgetlocal( 142, "NOHIGHLIGHT");
+ EIGHTBIT = catgetlocal( 143, "EIGHTBIT");
+ NOEIGHTBIT = catgetlocal( 144, "NOEIGHTBIT");
+ /*
+ | additions
+ */
+ mode_strings[7] = catgetlocal( 145, "emacs key bindings ");
+ emacs_help_text[0] = help_text[0];
+ emacs_help_text[1] = catgetlocal( 146, "^a beginning of line ^i tab ^r restore word ");
+ emacs_help_text[2] = catgetlocal( 147, "^b back 1 char ^j undel char ^t top of text ");
+ emacs_help_text[3] = catgetlocal( 148, "^c command ^k delete line ^u bottom of text ");
+ emacs_help_text[4] = catgetlocal( 149, "^d delete char ^l undelete line ^v next page ");
+ emacs_help_text[5] = catgetlocal( 150, "^e end of line ^m newline ^w delete word ");
+ emacs_help_text[6] = catgetlocal( 151, "^f forward 1 char ^n next line ^x search ");
+ emacs_help_text[7] = catgetlocal( 152, "^g go back 1 page ^o ascii char insert ^y search prompt ");
+ emacs_help_text[8] = catgetlocal( 153, "^h backspace ^p prev line ^z next word ");
+ emacs_help_text[9] = help_text[9];
+ emacs_help_text[10] = help_text[10];
+ emacs_help_text[11] = help_text[11];
+ emacs_help_text[12] = help_text[12];
+ emacs_help_text[13] = help_text[13];
+ emacs_help_text[14] = help_text[14];
+ emacs_help_text[15] = help_text[15];
+ emacs_help_text[16] = help_text[16];
+ emacs_help_text[17] = help_text[17];
+ emacs_help_text[18] = help_text[18];
+ emacs_help_text[19] = help_text[19];
+ emacs_help_text[20] = help_text[20];
+ emacs_help_text[21] = help_text[21];
+ emacs_control_keys[0] = catgetlocal( 154, "^[ (escape) menu ^y search prompt ^k delete line ^p prev li ^g prev page");
+ emacs_control_keys[1] = catgetlocal( 155, "^o ascii code ^x search ^l undelete line ^n next li ^v next page");
+ emacs_control_keys[2] = catgetlocal( 156, "^u end of file ^a begin of line ^w delete word ^b back 1 char ");
+ emacs_control_keys[3] = catgetlocal( 157, "^t top of text ^e end of line ^r restore word ^f forward 1 char ");
+ emacs_control_keys[4] = catgetlocal( 158, "^c command ^d delete char ^j undelete char ^z next word ");
+ EMACS_string = catgetlocal( 159, "EMACS");
+ NOEMACS_string = catgetlocal( 160, "NOEMACS");
+ usage4 = catgetlocal( 161, " +# put cursor at line #\n");
+
+ commands[0] = HELP;
+ commands[1] = WRITE;
+ commands[2] = READ;
+ commands[3] = LINE;
+ commands[4] = FILE_str;
+ commands[5] = REDRAW;
+ commands[6] = RESEQUENCE;
+ commands[7] = AUTHOR;
+ commands[8] = VERSION;
+ commands[9] = CASE;
+ commands[10] = NOCASE;
+ commands[11] = EXPAND;
+ commands[12] = NOEXPAND;
+ commands[13] = Exit_string;
+ commands[14] = QUIT_string;
+ commands[15] = "<";
+ commands[16] = ">";
+ commands[17] = "!";
+ commands[18] = "0";
+ commands[19] = "1";
+ commands[20] = "2";
+ commands[21] = "3";
+ commands[22] = "4";
+ commands[23] = "5";
+ commands[24] = "6";
+ commands[25] = "7";
+ commands[26] = "8";
+ commands[27] = "9";
+ commands[28] = CHARACTER;
+ commands[29] = NULL;
+ init_strings[0] = CASE;
+ init_strings[1] = NOCASE;
+ init_strings[2] = EXPAND;
+ init_strings[3] = NOEXPAND;
+ init_strings[4] = INFO;
+ init_strings[5] = NOINFO;
+ init_strings[6] = MARGINS;
+ init_strings[7] = NOMARGINS;
+ init_strings[8] = AUTOFORMAT;
+ init_strings[9] = NOAUTOFORMAT;
+ init_strings[10] = Echo;
+ init_strings[11] = PRINTCOMMAND;
+ init_strings[12] = RIGHTMARGIN;
+ init_strings[13] = HIGHLIGHT;
+ init_strings[14] = NOHIGHLIGHT;
+ init_strings[15] = EIGHTBIT;
+ init_strings[16] = NOEIGHTBIT;
+ init_strings[17] = EMACS_string;
+ init_strings[18] = NOEMACS_string;
+ init_strings[19] = NULL;
+
+ /*
+ | allocate space for strings here for settings menu
+ */
+
+ for (counter = 1; counter < NUM_MODES_ITEMS; counter++)
+ {
+ modes_menu[counter].item_string = malloc(80);
+ }
+
+#ifndef NO_CATGETS
+ catclose(catalog);
+#endif /* NO_CATGETS */
+}
+
diff --git a/usr.bin/ee/nls/en_US.ISO_8859-1/ee.msg b/usr.bin/ee/nls/en_US.ISO_8859-1/ee.msg
new file mode 100644
index 0000000000000..1ed22aa1bed48
--- /dev/null
+++ b/usr.bin/ee/nls/en_US.ISO_8859-1/ee.msg
@@ -0,0 +1,170 @@
+$ This file contains the messages for ee ("easy editor"). See the file
+$ ee.i18n.guide for more information
+$
+$ For ee patchlevel 3
+$
+$ $Header: /home/ncvs/src/usr.bin/ee/ee.msg,v 1.1.1.1 1995/08/30 07:28:06 jkh Exp $
+$
+$set 1
+$quote "
+1 "modes menu"
+2 "tabs to spaces "
+3 "case sensitive search"
+4 "margins observed "
+5 "auto-paragraph format"
+6 "eightbit characters "
+7 "info window "
+8 "right margin "
+9 "leave menu"
+10 "save changes"
+11 "no save"
+12 "file menu"
+13 "read a file"
+14 "write a file"
+15 "save file"
+16 "print editor contents"
+17 "search menu"
+18 "search for ..."
+19 "search"
+20 "spell menu"
+21 "use 'spell'"
+22 "use 'ispell'"
+23 "miscellaneous menu"
+24 "format paragraph"
+25 "shell command"
+26 "check spelling"
+27 "main menu"
+28 "leave editor"
+29 "help"
+30 "file operations"
+31 "redraw screen"
+32 "settings"
+33 "search"
+34 "miscellaneous"
+35 "Control keys: "
+36 "^a ascii code ^i tab ^r right "
+37 "^b bottom of text ^j newline ^t top of text "
+38 "^c command ^k delete char ^u up "
+39 "^d down ^l left ^v undelete word "
+40 "^e search prompt ^m newline ^w delete word "
+41 "^f undelete char ^n next page ^x search "
+42 "^g begin of line ^o end of line ^y delete line "
+43 "^h backspace ^p prev page ^z undelete line "
+44 "^[ (escape) menu "
+45 " "
+46 "Commands: "
+47 "help : get this info file : print file name "
+48 "read : read a file char : ascii code of char "
+49 "write : write a file case : case sensitive search "
+50 "exit : leave and save nocase : case insensitive search "
+51 "quit : leave, no save !cmd : execute \"cmd\" in shell "
+52 "line : display line # 0-9 : go to line \"#\" "
+53 "expand : expand tabs noexpand: do not expand tabs "
+54 " "
+55 " ee [-i] [-e] [-h] [file(s)] "
+56 " -i : no information window -e : do not expand tabs -h : no highlight "
+57 "^[ (escape) menu ^e search prompt ^y delete line ^u up ^p prev page "
+58 "^a ascii code ^x search ^z undelete line ^d down ^n next page "
+59 "^b bottom of text ^g begin of line ^w delete word ^l left "
+60 "^t top of text ^o end of line ^v undelete word ^r right "
+61 "^c command ^k delete char ^f undelete char "
+62 "help : get help info |file : print file name |line : print line # "
+63 "read : read a file |char : ascii code of char |0-9 : go to line \"#\""
+64 "write: write a file |case : case sensitive search |exit : leave and save "
+65 "!cmd : shell \"cmd\" |nocase: ignore case in search |quit : leave, no save"
+66 "expand: expand tabs |noexpand: do not expand tabs "
+67 " press Escape (^[) for menu"
+68 "no file"
+69 "ascii code: "
+70 "sending contents of buffer to \"%s\" "
+71 "command: "
+72 "name of file to write: "
+73 "name of file to read: "
+74 "character = %d"
+75 "unknown command \"%s\""
+76 "entered command is not unique"
+77 "line %d "
+78 "length = %d"
+79 "current file is \"%s\" "
+80 "usage: %s [-i] [-e] [-h] [+line_number] [file(s)]\n"
+81 " -i turn off info window\n"
+82 " -e do not convert tabs to spaces\n"
+83 " -h do not use highlighting\n"
+84 "file \"%s\" is a directory"
+85 "new file \"%s\""
+86 "can't open \"%s\""
+87 "file \"%s\", %d lines"
+88 "finished reading file \"%s\""
+89 "reading file \"%s\""
+90 ", read only"
+91 "file \"%s\", %d lines"
+92 "enter name of file: "
+93 "no filename entered: file not saved"
+94 "changes have been made, are you sure? (y/n [n]) "
+95 "y"
+96 "file already exists, overwrite? (y/n) [n] "
+97 "unable to create file \"%s\""
+98 "writing file \"%s\""
+99 "\"%s\" %d lines, %d characters"
+100 " ...searching"
+101 "string \"%s\" not found"
+102 "search for: "
+103 "could not exec %s\n"
+104 "press return to continue "
+105 "press Esc to cancel"
+106 "menu too large for window"
+107 "press any key to continue "
+108 "shell command: "
+109 "...formatting paragraph..."
+110 "<!echo 'list of unrecognized words'; echo -=-=-=-=-=-"
+111 "sending contents of edit buffer to 'spell'"
+112 "right margin is: "
+113 "restricted mode: unable to perform requested operation"
+114 "ON"
+115 "OFF"
+116 "HELP"
+117 "WRITE"
+118 "READ"
+119 "LINE"
+120 "FILE"
+121 "CHARACTER"
+122 "REDRAW"
+123 "RESEQUENCE"
+124 "AUTHOR"
+125 "VERSION"
+126 "CASE"
+127 "NOCASE"
+128 "EXPAND"
+129 "NOEXPAND"
+130 "EXIT"
+131 "QUIT"
+132 "INFO"
+133 "NOINFO"
+134 "MARGINS"
+135 "NOMARGINS"
+136 "AUTOFORMAT"
+137 "NOAUTOFORMAT"
+138 "ECHO"
+139 "PRINTCOMMAND"
+140 "RIGHTMARGIN"
+141 "HIGHLIGHT"
+142 "NOHIGHLIGHT"
+143 "EIGHTBIT"
+144 "NOEIGHTBIT"
+145 "emacs key bindings "
+146 "^a beginning of line ^i tab ^r restore word "
+147 "^b back 1 char ^j undel char ^t top of text "
+148 "^c command ^k delete line ^u bottom of text "
+149 "^d delete char ^l undelete line ^v next page "
+150 "^e end of line ^m newline ^w delete word "
+151 "^f forward 1 char ^n next line ^x search "
+152 "^g go back 1 page ^o ascii char insert ^y search prompt "
+153 "^h backspace ^p prev line ^z next word "
+154 "^[ (escape) menu ^y search prompt ^k delete line ^p prev li ^g prev page"
+155 "^o ascii code ^x search ^l undelete line ^n next li ^v next page"
+156 "^u end of file ^a begin of line ^w delete word ^b back 1 char "
+157 "^t top of text ^e end of line ^r restore word ^f forward 1 char "
+158 "^c command ^d delete char ^j undelete char ^z next word "
+159 "EMACS"
+160 "NOEMACS"
+161 " +# put cursor at line #\n"
diff --git a/usr.bin/killall/Makefile b/usr.bin/killall/Makefile
new file mode 100644
index 0000000000000..17cfc53c0e9a4
--- /dev/null
+++ b/usr.bin/killall/Makefile
@@ -0,0 +1,7 @@
+MAN1= killall.1
+
+beforeinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${.CURDIR}/killall.pl ${DESTDIR}${BINDIR}/killall
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/cdcontrol/Makefile b/usr.sbin/cdcontrol/Makefile
new file mode 100644
index 0000000000000..86a42ebfab7f3
--- /dev/null
+++ b/usr.sbin/cdcontrol/Makefile
@@ -0,0 +1,4 @@
+PROG= cdcontrol
+CFLAGS+= -Wall
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/cdcontrol/cdcontrol.1 b/usr.sbin/cdcontrol/cdcontrol.1
new file mode 100644
index 0000000000000..095c170c756e1
--- /dev/null
+++ b/usr.sbin/cdcontrol/cdcontrol.1
@@ -0,0 +1,144 @@
+.Dd July 3, 1995
+.Dt CDCONTROL 1
+.Os FreeBSD
+.Sh NAME
+.Nm cdcontrol
+.Nd compact disc control utility
+.Sh SYNOPSIS
+.Nm cdcontrol
+.Op Fl s
+.Op Fl v
+.Op Fl f Ar discname
+.Op Ar command args...
+.Sh DESCRIPTION
+.Nm cdcontrol
+is a program to control audio features of a CD drive. The device is a name such
+as cd0 or mcd0.
+.Pp
+If the device not specified, the environment variable
+.Ev DISC
+will be used to find the cd device.
+.Pp
+If no command is given, then
+.Nm cdcontrol
+enters an interactive mode, reading commands from the standard input.
+.Pp
+The following options are available:
+.Bl -tag -width flag
+.It Fl s
+Silent mode - do not print table headers and human readable comments.
+.It Fl v
+Verbose mode - print as much information as possible.
+.It Fl f Ar discname
+Specifies a device name, such as /dev/cd0c or mcd0.
+Both absolute path and relative to /dev filename are possible.
+Suffix `c' is added to the device name if needed.
+.El
+.Pp
+The available commands are listed below. Only as many
+characters as are required to uniquely identify a command
+need be specified.
+.Bl -tag -width Cm
+
+.It Cm play Op Ar first_track Op Ar last_track
+Play from track
+.Nm first_track
+to track
+.Nm last_track.
+The first track has number 1.
+
+.It Cm play Ar start_m:start_s.start_f Op Ar end_m:end_s.end_f
+Play from the absolute address
+(MSF) defined by
+.Nm start_m
+in minutes,
+.Nm start_s,
+in seconds and
+.Nm start_f
+(frame number) to the abolute address defined by
+.Nm end_m
+in minutes,
+.Nm end_s,
+in seconds and
+.Nm end_f
+(frame number). Minutes are in the range 0-99. Seconds are in the range 0-59.
+Frame numbers are in the range 0-74.
+
+.It Cm play Ar #start_block Op length
+Play starting from the logical block
+.Nm start_block
+using
+.Nm length
+logical blocks.
+
+.It Cm pause
+Stop playing. Do not stop the disc.
+
+.It Cm resume
+Resume playing. Used after the
+.Nm pause
+ command.
+
+.It Cm stop
+Stop the disc.
+
+.It Cm eject
+Eject the disc.
+
+.It Cm volume Ar left_channel Ar right_channel
+Set the volume of left channel to
+.Nm left_channel
+and the volume of right channel to
+.Nm right_channel.
+Allowed values are in the range 0-255.
+
+.It Cm volume Ar mute
+Turn the sound off.
+
+.It Cm volume Ar mono
+Set the mono mode.
+
+.It Cm volume Ar stereo
+Set the stereo mode.
+
+.It Cm volume Ar left
+Play the left subtrack on both left and right channels.
+
+.It Cm volume Ar right
+Play the right subtrack on both left and right channels.
+
+.It Cm info
+Print the information about the disc:
+the current playing status and position,
+the current values of the volume for left and right channels,
+and the table of contents.
+
+.It Cm help
+Print the list of available commands.
+
+.It Cm debug Ar on
+Enable the debugging mode of the CD device driver.
+
+.It Cm debug Ar off
+Disable the driver debugging mode.
+
+.It Cm debug Ar reset
+Perform the hardware reset of the device.
+
+.It Cm quit
+Quit the program.
+
+.Sh FILES
+.Bl -tag -width /dev/rmcd0c -compact
+.It Pa /dev/rcd0c
+.It Pa /dev/rmcd0c
+.It Pa /dev/rwcd0c
+.El
+.Sh AUTHORS
+Jean-Marc Zucconi,
+Andrew A.\ Chernov,
+Serge V.\ Vakulenko
+.Sh HISTORY
+The
+.Nm cdcontrol
+command appeared in FreeBSD 2.1
diff --git a/usr.sbin/cdcontrol/cdcontrol.c b/usr.sbin/cdcontrol/cdcontrol.c
new file mode 100644
index 0000000000000..8a8274aef8744
--- /dev/null
+++ b/usr.sbin/cdcontrol/cdcontrol.c
@@ -0,0 +1,622 @@
+/*
+ * Compact Disc Control Utility by Serge V. Vakulenko, <vak@cronyx.ru>.
+ * Based on the non-X based CD player by Jean-Marc Zucconi and
+ * Andrew A. Chernov.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/file.h>
+#include <sys/cdio.h>
+#include <sys/ioctl.h>
+
+#define VERSION "1.0"
+
+/*
+ * Audio Status Codes
+ */
+#define ASTS_INVALID 0x00 /* Audio status byte not valid */
+#define ASTS_PLAYING 0x11 /* Audio play operation in progress */
+#define ASTS_PAUSED 0x12 /* Audio play operation paused */
+#define ASTS_COMPLETED 0x13 /* Audio play operation successfully completed */
+#define ASTS_ERROR 0x14 /* Audio play operation stopped due to error */
+#define ASTS_VOID 0x15 /* No current audio status to return */
+
+struct cmdtab {
+ int command;
+ char *name;
+ char *args;
+} cmdtab[] = {
+#define CMD_DEBUG 1
+ { CMD_DEBUG, "Debug", "[ on | off | reset ]", },
+#define CMD_EJECT 2
+ { CMD_EJECT, "Eject", "", },
+#define CMD_HELP 3
+ { CMD_HELP, "?", 0, },
+ { CMD_HELP, "Help", "", },
+#define CMD_INFO 4
+ { CMD_INFO, "Info", "", },
+#define CMD_PAUSE 5
+ { CMD_PAUSE, "PAuse", "", },
+#define CMD_PLAY 6
+ { CMD_PLAY, "P", 0, },
+ { CMD_PLAY, "Play", "min1:sec1.fr1 [ min2:sec2.fr2 ]", },
+ { CMD_PLAY, "Play", "track1.index1 [ track2.index2 ]", },
+ { CMD_PLAY, "Play", "#block [ len ]", },
+#define CMD_QUIT 7
+ { CMD_QUIT, "Quit", "", },
+#define CMD_RESUME 8
+ { CMD_RESUME, "Resume", "", },
+#define CMD_STOP 9
+ { CMD_STOP, "Stop", "", },
+#define CMD_VOLUME 10
+ { CMD_VOLUME, "Volume", "<l> <r> | left | right | mute | mono | stereo", },
+ { 0, 0, },
+};
+
+struct cd_toc_entry toc_buffer[100];
+
+char *cdname;
+int fd = -1;
+int verbose = 1;
+
+extern char *optarg;
+extern int optind;
+
+int setvol (int, int);
+int read_toc_entrys (int);
+int play_msf (int, int, int, int, int, int);
+int play_track (int, int, int, int);
+int get_vol (int *, int *);
+int status (int *, int *, int *, int *);
+int open_cd (void);
+int play (char *arg);
+int info (char *arg);
+char *input (int*);
+void prtrack (struct cd_toc_entry *e, int lastflag);
+void lba2msf (int lba, u_char *m, u_char *s, u_char *f);
+int msf2lba (u_char m, u_char s, u_char f);
+int play_blocks (int blk, int len);
+int run (int cmd, char *arg);
+char *parse (char *buf, int *cmd);
+
+extern int errno;
+
+void help ()
+{
+ struct cmdtab *c;
+
+ for (c=cmdtab; c->name; ++c) {
+ if (! c->args)
+ continue;
+ printf ("\t%s", c->name);
+ if (*c->args)
+ printf (" %s", c->args);
+ printf ("\n");
+ }
+}
+
+void usage ()
+{
+ printf ("Usage:\n\tcdcontrol [ -vs ] [ -f disc ] [ command args... ]\n");
+ printf ("Options:\n");
+ printf ("\t-v - verbose mode\n");
+ printf ("\t-s - silent mode\n");
+ printf ("\t-f disc - device name such as /dev/cd0c\n");
+ printf ("\tDISC - shell variable with device name\n");
+ printf ("Commands:\n");
+ help ();
+ exit (1);
+}
+
+int main (int argc, char **argv)
+{
+ int cmd;
+ char *arg;
+
+ cdname = getenv ("DISC");
+ if (! cdname)
+ cdname = getenv ("CDPLAY");
+
+ for (;;) {
+ switch (getopt (argc, argv, "svhf:")) {
+ case EOF:
+ break;
+ case 's':
+ verbose = 0;
+ continue;
+ case 'v':
+ verbose = 2;
+ continue;
+ case 'f':
+ cdname = optarg;
+ continue;
+ case 'h':
+ default:
+ usage ();
+ }
+ break;
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0 && strcasecmp (*argv, "help") == 0)
+ usage ();
+
+ if (! cdname) {
+ fprintf (stderr, "No CD device name specified.\n");
+ usage ();
+ }
+
+ if (argc > 0) {
+ char buf[80], *p;
+ int len;
+
+ for (p=buf; argc-- > 0; ++argv) {
+ len = strlen (*argv);
+ if (p + len >= buf + sizeof (buf) - 1)
+ usage ();
+ if (p > buf)
+ *p++ = ' ';
+ strcpy (p, *argv);
+ p += len;
+ }
+ *p = 0;
+ arg = parse (buf, &cmd);
+ return run (cmd, arg);
+ }
+
+ if (verbose == 1)
+ verbose = isatty (0);
+ if (verbose) {
+ printf ("Compact Disc Control Utility, Version %s\n", VERSION);
+ printf ("Type `?' for command list\n\n");
+ }
+
+ for (;;) {
+ arg = input (&cmd);
+ if (run (cmd, arg) < 0) {
+ if (verbose)
+ perror ("cdplay");
+ close (fd);
+ fd = -1;
+ }
+ fflush (stdout);
+ }
+}
+
+int run (int cmd, char *arg)
+{
+ int l, r, rc;
+
+ switch (cmd) {
+ case CMD_QUIT:
+ exit (0);
+
+ default:
+ case CMD_HELP:
+ help ();
+ return (0);
+
+ case CMD_INFO:
+ if (fd<0 && ! open_cd ()) return (0);
+ return info (arg);
+
+ case CMD_PAUSE:
+ if (fd<0 && ! open_cd ()) return (0);
+ return ioctl (fd, CDIOCPAUSE);
+
+ case CMD_RESUME:
+ if (fd<0 && ! open_cd ()) return (0);
+ return ioctl (fd, CDIOCRESUME);
+
+ case CMD_STOP:
+ if (fd<0 && ! open_cd ()) return (0);
+ return ioctl (fd, CDIOCSTOP);
+
+ case CMD_DEBUG:
+ if (fd<0 && ! open_cd ()) return (0);
+ if (strcasecmp (arg, "on") == 0)
+ return ioctl (fd, CDIOCSETDEBUG);
+ if (strcasecmp (arg, "off") == 0)
+ return ioctl (fd, CDIOCCLRDEBUG);
+ if (strcasecmp (arg, "reset") == 0)
+ return ioctl (fd, CDIOCRESET);
+ printf ("Invalid command arguments\n");
+ return (0);
+
+ case CMD_EJECT:
+ if (fd<0 && ! open_cd ()) return (0);
+ (void) ioctl (fd, CDIOCALLOW);
+ rc = ioctl (fd, CDIOCEJECT);
+ if (rc < 0)
+ return (rc);
+ close (fd);
+ fd = -1;
+ return (0);
+
+ case CMD_PLAY:
+ if (fd<0 && ! open_cd ()) return (0);
+ return play (arg);
+
+ case CMD_VOLUME:
+ if (fd<0 && ! open_cd ()) return (0);
+
+ if (strcasecmp (arg, "left") == 0)
+ return ioctl (fd, CDIOCSETLEFT);
+ else if (strcasecmp (arg, "right") == 0)
+ return ioctl (fd, CDIOCSETRIGHT);
+ else if (strcasecmp (arg, "mute") == 0)
+ return ioctl (fd, CDIOCSETMUTE);
+ else if (strcasecmp (arg, "mono") == 0)
+ return ioctl (fd, CDIOCSETMONO);
+ else if (strcasecmp (arg, "stereo") == 0)
+ return ioctl (fd, CDIOCSETSTERIO);
+
+ if (2 != sscanf (arg, "%d %d", &l, &r)) {
+ printf ("Invalid command arguments\n");
+ return (0);
+ }
+ return setvol (l, r);
+ }
+}
+
+int play (char *arg)
+{
+ struct ioc_toc_header h;
+ int rc, n, start, end = 0, istart = 1, iend = 1;
+
+ rc = ioctl (fd, CDIOREADTOCHEADER, &h);
+ if (rc < 0)
+ return (rc);
+
+ n = h.ending_track - h.starting_track + 1;
+ rc = read_toc_entrys ((n + 1) * sizeof (struct cd_toc_entry));
+ if (rc < 0)
+ return (rc);
+
+ if (! *arg)
+ /*
+ * Play the whole disc
+ */
+ return play_blocks (0, msf2lba (toc_buffer[n].addr.msf.minute,
+ toc_buffer[n].addr.msf.second,
+ toc_buffer[n].addr.msf.frame));
+
+ if (strchr (arg, '#')) {
+ /*
+ * Play block #blk [ len ]
+ */
+ int blk, len = 0;
+
+ if (2 != sscanf (arg, "#%d%d", &blk, &len) &&
+ 1 != sscanf (arg, "#%d", &blk)) {
+err: printf ("Invalid command arguments\n");
+ return (0);
+ }
+ if (len == 0)
+ len = msf2lba (toc_buffer[n].addr.msf.minute,
+ toc_buffer[n].addr.msf.second,
+ toc_buffer[n].addr.msf.frame) - blk;
+ return play_blocks (blk, len);
+ }
+
+ if (strchr (arg, ':')) {
+ /*
+ * Play MSF m1:s1 [ .f1 ] [ m2:s2 [ .f2 ] ]
+ */
+ int m1, m2 = 0, s1, s2 = 0, f1 = 0, f2 = 0;
+
+ if (6 != sscanf (arg, "%d:%d.%d%d:%d.%d", &m1, &s1, &f1, &m2, &s2, &f2) &&
+ 5 != sscanf (arg, "%d:%d.%d%d:%d", &m1, &s1, &f1, &m2, &s2) &&
+ 5 != sscanf (arg, "%d:%d%d:%d.%d", &m1, &s1, &m2, &s2, &f2) &&
+ 3 != sscanf (arg, "%d:%d.%d", &m1, &s1, &f1) &&
+ 4 != sscanf (arg, "%d:%d%d:%d", &m1, &s1, &m2, &s2) &&
+ 2 != sscanf (arg, "%d:%d", &m1, &s1))
+ goto err;
+ if (m2 == 0) {
+ m2 = toc_buffer[n].addr.msf.minute;
+ s2 = toc_buffer[n].addr.msf.second;
+ f2 = toc_buffer[n].addr.msf.frame;
+ }
+ return play_msf (m1, s1, f1, m2, s2, f2);
+ }
+
+ /*
+ * Play track trk1 [ .idx1 ] [ trk2 [ .idx2 ] ]
+ */
+ if (4 != sscanf (arg, "%d.%d%d.%d", &start, &istart, &end, &iend) &&
+ 3 != sscanf (arg, "%d.%d%d", &start, &istart, &end) &&
+ 3 != sscanf (arg, "%d%d.%d", &start, &end, &iend) &&
+ 2 != sscanf (arg, "%d.%d", &start, &istart) &&
+ 2 != sscanf (arg, "%d%d", &start, &end) &&
+ 1 != sscanf (arg, "%d", &start))
+ goto err;
+ if (end == 0)
+ end = n;
+ return play_track (start, istart, end, iend);
+}
+
+char *strstatus (int sts)
+{
+ switch (sts) {
+ case ASTS_INVALID: return ("invalid");
+ case ASTS_PLAYING: return ("playing");
+ case ASTS_PAUSED: return ("paused");
+ case ASTS_COMPLETED: return ("completed");
+ case ASTS_ERROR: return ("error");
+ case ASTS_VOID: return ("void");
+ default: return ("??");
+ }
+}
+
+int info (char *arg)
+{
+ struct ioc_toc_header h;
+ struct ioc_vol v;
+ int rc, i, n, trk, m, s, f;
+
+ rc = status (&trk, &m, &s, &f);
+ if (rc >= 0)
+ if (verbose)
+ printf ("Audio status = %d<%s>, current track = %d, current position = %d:%02d.%02d\n",
+ rc, strstatus (rc), trk, m, s, f);
+ else
+ printf ("%d %d %d:%02d.%02d\n", rc, trk, m, s, f);
+ else
+ printf ("No current status info\n");
+
+ rc = ioctl (fd, CDIOCGETVOL, &v);
+ if (rc >= 0)
+ if (verbose)
+ printf ("Left volume = %d, right volume = %d\n",
+ v.vol[0], v.vol[1]);
+ else
+ printf ("%d %d\n", v.vol[0], v.vol[1]);
+ else
+ printf ("No volume info\n");
+
+ rc = ioctl (fd, CDIOREADTOCHEADER, &h);
+ if (rc >= 0)
+ if (verbose)
+ printf ("Starting track = %d, ending track = %d, TOC size = %d bytes\n",
+ h.starting_track, h.ending_track, h.len);
+ else
+ printf ("%d %d %d\n", h.starting_track,
+ h.ending_track, h.len);
+ else {
+ perror ("getting toc header");
+ return (rc);
+ }
+
+ n = h.ending_track - h.starting_track + 1;
+ rc = read_toc_entrys ((n + 1) * sizeof (struct cd_toc_entry));
+ if (rc < 0)
+ return (rc);
+ if (verbose) {
+ printf ("track start duration block length type\n");
+ printf ("-------------------------------------------------\n");
+ }
+ for (i = 0; i < n; i++) {
+ printf ("%5d ", toc_buffer[i].track);
+ prtrack (toc_buffer + i, 0);
+ }
+ printf (" end ");
+ prtrack (toc_buffer + n, 1);
+ return (0);
+}
+
+void lba2msf (int lba, u_char *m, u_char *s, u_char *f)
+{
+ lba += 150; /* block start offset */
+ lba &= 0xffffff; /* negative lbas use only 24 bits */
+ *m = lba / (60 * 75);
+ lba %= (60 * 75);
+ *s = lba / 75;
+ *f = lba % 75;
+}
+
+int msf2lba (u_char m, u_char s, u_char f)
+{
+ return (((m * 60) + s) * 75 + f) - 150;
+}
+
+void prtrack (struct cd_toc_entry *e, int lastflag)
+{
+ int block, next, len;
+ u_char m, s, f;
+
+ /* Print track start */
+ printf ("%2d:%02d.%02d ", e->addr.msf.minute,
+ e->addr.msf.second, e->addr.msf.frame);
+
+ block = msf2lba (e->addr.msf.minute, e->addr.msf.second,
+ e->addr.msf.frame);
+ if (lastflag) {
+ /* Last track -- print block */
+ printf (" - %6d - -\n", block);
+ return;
+ }
+
+ next = msf2lba (e[1].addr.msf.minute, e[1].addr.msf.second,
+ e[1].addr.msf.frame);
+ len = next - block;
+ lba2msf (len, &m, &s, &f);
+
+ /* Print duration, block, length, type */
+ printf ("%2d:%02d.%02d %6d %6d %5s\n", m, s, f, block, len,
+ e->control & 4 ? "data" : "audio");
+}
+
+int play_track (int tstart, int istart, int tend, int iend)
+{
+ struct ioc_play_track t;
+
+ t.start_track = tstart;
+ t.start_index = istart;
+ t.end_track = tend;
+ t.end_index = iend;
+ return ioctl (fd, CDIOCPLAYTRACKS, &t);
+}
+
+int play_blocks (int blk, int len)
+{
+ struct ioc_play_blocks t;
+
+ t.blk = blk;
+ t.len = len;
+ return ioctl (fd, CDIOCPLAYBLOCKS, &t);
+}
+
+int setvol (int l, int r)
+{
+ struct ioc_vol v;
+
+ v.vol[0] = l;
+ v.vol[1] = r;
+ v.vol[2] = 0;
+ v.vol[3] = 0;
+ return ioctl (fd, CDIOCSETVOL, &v);
+}
+
+int read_toc_entrys (int len)
+{
+ struct ioc_read_toc_entry t;
+
+ t.address_format = CD_MSF_FORMAT;
+ t.starting_track = 1;
+ t.data_len = len;
+ t.data = toc_buffer;
+ return ioctl (fd, CDIOREADTOCENTRYS, (char *) &t);
+}
+
+int play_msf (int start_m, int start_s, int start_f,
+ int end_m, int end_s, int end_f)
+{
+ struct ioc_play_msf a;
+
+ a.start_m = start_m;
+ a.start_s = start_s;
+ a.start_f = start_f;
+ a.end_m = end_m;
+ a.end_s = end_s;
+ a.end_f = end_f;
+ return ioctl (fd, CDIOCPLAYMSF, (char *) &a);
+}
+
+int status (int *trk, int *min, int *sec, int *frame)
+{
+ struct ioc_read_subchannel s;
+ struct cd_sub_channel_info data;
+
+ bzero (&s, sizeof (s));
+ s.data = &data;
+ s.data_len = sizeof (data);
+ s.address_format = CD_MSF_FORMAT;
+ s.data_format = CD_CURRENT_POSITION;
+ if (ioctl (fd, CDIOCREADSUBCHANNEL, (char *) &s) < 0)
+ return -1;
+ *trk = s.data->what.position.track_number;
+ *min = s.data->what.position.reladdr.msf.minute;
+ *sec = s.data->what.position.reladdr.msf.second;
+ *frame = s.data->what.position.reladdr.msf.frame;
+ return s.data->header.audio_status;
+}
+
+char *input (int *cmd)
+{
+ static char buf[80];
+ char *p;
+
+ do {
+ if (verbose)
+ fprintf (stderr, "cd> ");
+ if (! fgets (buf, sizeof (buf), stdin)) {
+ *cmd = CMD_QUIT;
+ return 0;
+ }
+ p = parse (buf, cmd);
+ } while (! p);
+ return (p);
+}
+
+char *parse (char *buf, int *cmd)
+{
+ struct cmdtab *c;
+ char *p;
+ int len;
+
+ for (p=buf; *p; ++p)
+ if (*p == '\t')
+ *p = ' ';
+ else if (*p == '\n')
+ *p = 0;
+
+ for (p=buf; *p; ++p)
+ if (*p == ' ') {
+ *p++ = 0;
+ break;
+ }
+ while (*p == ' ')
+ ++p;
+
+ len = strlen (buf);
+ if (! len)
+ return (0);
+ *cmd = -1;
+ for (c=cmdtab; c->name; ++c) {
+ /* Try short command form. */
+ if (! c->args && len == strlen (c->name) &&
+ strncasecmp (buf, c->name, len) == 0) {
+ *cmd = c->command;
+ break;
+ }
+
+ /* Try long form. */
+ if (strncasecmp (buf, c->name, len) != 0)
+ continue;
+
+ /* Check inambiguity. */
+ if (*cmd != -1) {
+ fprintf (stderr, "Ambiguous command\n");
+ return (0);
+ }
+ *cmd = c->command;
+ }
+ if (*cmd == -1) {
+ fprintf (stderr, "Invalid command, enter ``help'' for command list\n");
+ return (0);
+ }
+ return p;
+}
+
+int open_cd ()
+{
+ char devbuf[80];
+
+ if (fd > -1)
+ return (1);
+ if (*cdname == '/')
+ strcpy (devbuf, cdname);
+ else if (*cdname == 'r')
+ sprintf (devbuf, "/dev/%s", cdname);
+ else
+ sprintf (devbuf, "/dev/r%s", cdname);
+ fd = open (devbuf, O_RDONLY);
+ if (fd < 0 && errno == ENOENT) {
+ strcat (devbuf, "c");
+ fd = open (devbuf, O_RDONLY);
+ }
+ if (fd < 0) {
+ if (errno != ENXIO) {
+ perror (devbuf);
+ exit (1);
+ }
+ /* open says 'Device not configured' if no cd in */
+ fprintf (stderr, "open: No CD in\n");
+ return (0);
+ }
+ return (1);
+}
diff --git a/usr.sbin/mrouted/cfparse.y b/usr.sbin/mrouted/cfparse.y
new file mode 100644
index 0000000000000..c08938d4a47a2
--- /dev/null
+++ b/usr.sbin/mrouted/cfparse.y
@@ -0,0 +1,564 @@
+%{
+/*
+ * Configuration file parser for mrouted.
+ *
+ * Written by Bill Fenner, NRL, 1994
+ *
+ * $Id: cfparse.y,v 3.6 1995/06/25 18:49:46 fenner Exp $
+ */
+#include <stdio.h>
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "defs.h"
+
+/*
+ * Local function declarations
+ */
+static void fatal __P((char *fmt, ...));
+static void warn __P((char *fmt, ...));
+static void yyerror __P((char *s));
+static char * next_word __P((void));
+static int yylex __P((void));
+static u_int32 valid_if __P((char *s));
+static struct ifreq * ifconfaddr __P((struct ifconf *ifcp, u_int32 a));
+int yyparse __P((void));
+
+static FILE *f;
+
+extern int udp_socket;
+char *configfilename = _PATH_MROUTED_CONF;
+
+extern int cache_lifetime;
+extern int max_prune_lifetime;
+
+static int lineno;
+static struct ifreq ifbuf[32];
+static struct ifconf ifc;
+
+static struct uvif *v;
+
+static int order;
+
+struct addrmask {
+ u_int32 addr;
+ int mask;
+};
+
+struct boundnam {
+ char *name;
+ struct addrmask bound;
+};
+
+#define MAXBOUNDS 20
+
+struct boundnam boundlist[MAXBOUNDS]; /* Max. of 20 named boundaries */
+int numbounds = 0; /* Number of named boundaries */
+
+%}
+
+%union
+{
+ int num;
+ char *ptr;
+ struct addrmask addrmask;
+ u_int32 addr;
+};
+
+%token CACHE_LIFETIME PRUNING
+%token PHYINT TUNNEL NAME
+%token DISABLE METRIC THRESHOLD RATE_LIMIT SRCRT BOUNDARY NETMASK ALTNET
+%token <num> BOOLEAN
+%token <num> NUMBER
+%token <ptr> STRING
+%token <addrmask> ADDRMASK
+%token <addr> ADDR
+
+%type <addr> interface
+%type <addrmask> bound boundary addrmask
+
+%start conf
+
+%%
+
+conf : stmts
+ ;
+
+stmts : /* Empty */
+ | stmts stmt
+ ;
+
+stmt : error
+ | PHYINT interface {
+
+ vifi_t vifi;
+
+ if (order)
+ fatal("phyints must appear before tunnels");
+
+ for (vifi = 0, v = uvifs;
+ vifi < numvifs;
+ ++vifi, ++v)
+ if (!(v->uv_flags & VIFF_TUNNEL) &&
+ $2 == v->uv_lcl_addr)
+ break;
+
+ if (vifi == numvifs)
+ fatal("%s is not a configured interface",
+ inet_fmt($2,s1));
+
+ /*log(LOG_INFO, 0, "phyint: %x\n", v);*/
+ }
+ ifmods
+ | TUNNEL interface ADDR {
+
+ struct ifreq *ifr;
+ struct ifreq ffr;
+ vifi_t vifi;
+
+ order++;
+
+ ifr = ifconfaddr(&ifc, $2);
+ if (ifr == 0)
+ fatal("Tunnel local address %s is not mine",
+ inet_fmt($2, s1));
+
+ strncpy(ffr.ifr_name, ifr->ifr_name, IFNAMSIZ);
+ if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ffr)<0)
+ fatal("ioctl SIOCGIFFLAGS on %s",ffr.ifr_name);
+ if (ffr.ifr_flags & IFF_LOOPBACK)
+ fatal("Tunnel local address %s is a loopback interface",
+ inet_fmt($2, s1));
+
+ if (ifconfaddr(&ifc, $3) != 0)
+ fatal("Tunnel remote address %s is one of mine",
+ inet_fmt($3, s1));
+
+ for (vifi = 0, v = uvifs;
+ vifi < numvifs;
+ ++vifi, ++v)
+ if (v->uv_flags & VIFF_TUNNEL) {
+ if ($3 == v->uv_rmt_addr)
+ fatal("Duplicate tunnel to %s",
+ inet_fmt($3, s1));
+ } else if (!(v->uv_flags & VIFF_DISABLED)) {
+ if (($3 & v->uv_subnetmask) == v->uv_subnet)
+ fatal("Unnecessary tunnel to %s",
+ inet_fmt($3,s1));
+ }
+
+ if (numvifs == MAXVIFS)
+ fatal("too many vifs");
+
+ v = &uvifs[numvifs];
+ v->uv_flags = VIFF_TUNNEL;
+ v->uv_metric = DEFAULT_METRIC;
+ v->uv_rate_limit= DEFAULT_TUN_RATE_LIMIT;
+ v->uv_threshold = DEFAULT_THRESHOLD;
+ v->uv_lcl_addr = $2;
+ v->uv_rmt_addr = $3;
+ v->uv_subnet = 0;
+ v->uv_subnetmask= 0;
+ v->uv_subnetbcast= 0;
+ strncpy(v->uv_name, ffr.ifr_name, IFNAMSIZ);
+ v->uv_groups = NULL;
+ v->uv_neighbors = NULL;
+ v->uv_acl = NULL;
+ v->uv_addrs = NULL;
+
+ if (!(ffr.ifr_flags & IFF_UP)) {
+ v->uv_flags |= VIFF_DOWN;
+ vifs_down = TRUE;
+ }
+ /*log(LOG_INFO, 0, "tunnel: %x\n", v);*/
+ }
+ tunnelmods
+ {
+ log(LOG_INFO, 0,
+ "installing tunnel from %s to %s as vif #%u - rate=%d",
+ inet_fmt($2, s1), inet_fmt($3, s2),
+ numvifs, v->uv_rate_limit);
+
+ ++numvifs;
+ }
+ | PRUNING BOOLEAN { pruning = $2; }
+ | CACHE_LIFETIME NUMBER { cache_lifetime = $2;
+ max_prune_lifetime = cache_lifetime * 2;
+ }
+ | NAME STRING boundary { if (numbounds >= MAXBOUNDS) {
+ fatal("Too many named boundaries (max %d)", MAXBOUNDS);
+ }
+
+ boundlist[numbounds].name = malloc(strlen($2) + 1);
+ strcpy(boundlist[numbounds].name, $2);
+ boundlist[numbounds++].bound = $3;
+ }
+ ;
+
+tunnelmods : /* empty */
+ | tunnelmods /*{ log(LOG_INFO, 0, "tunnelmod: %x", v); }*/ tunnelmod
+ ;
+
+tunnelmod : mod
+ | SRCRT { fatal("Source-route tunnels not supported"); }
+ ;
+
+ifmods : /* empty */
+ | ifmods /*{ log(LOG_INFO, 0, "ifmod: %x", v); }*/ ifmod
+ ;
+
+ifmod : mod
+ | DISABLE { v->uv_flags |= VIFF_DISABLED; }
+ | NETMASK ADDR {
+ u_int32 subnet, mask;
+
+ mask = $2;
+ subnet = v->uv_lcl_addr & mask;
+ if (!inet_valid_subnet(subnet, mask))
+ fatal("Invalid netmask");
+ v->uv_subnet = subnet;
+ v->uv_subnetmask = mask;
+ v->uv_subnetbcast = subnet | ~mask;
+ }
+ | ALTNET addrmask {
+
+ struct phaddr *ph;
+
+ ph = (struct phaddr *)malloc(sizeof(struct phaddr));
+ if (ph == NULL)
+ fatal("out of memory");
+ if ($2.mask) {
+ VAL_TO_MASK(ph->pa_subnetmask, $2.mask);
+ } else
+ ph->pa_subnetmask = v->uv_subnetmask;
+ ph->pa_subnet = $2.addr & ph->pa_subnetmask;
+ ph->pa_subnetbcast = ph->pa_subnet | ~ph->pa_subnetmask;
+ if ($2.addr & ~ph->pa_subnetmask)
+ warn("Extra subnet %s/%d has host bits set",
+ inet_fmt($2.addr,s1), $2.mask);
+ ph->pa_next = v->uv_addrs;
+ v->uv_addrs = ph;
+
+ }
+ ;
+
+mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255)
+ fatal("Invalid threshold %d",$2);
+ v->uv_threshold = $2;
+ }
+ | THRESHOLD {
+
+ warn("Expected number after threshold keyword");
+
+ }
+ | METRIC NUMBER { if ($2 < 1 || $2 > UNREACHABLE)
+ fatal("Invalid metric %d",$2);
+ v->uv_metric = $2;
+ }
+ | METRIC {
+
+ warn("Expected number after metric keyword");
+
+ }
+ | RATE_LIMIT NUMBER { if ($2 > MAX_RATE_LIMIT)
+ fatal("Invalid rate_limit %d",$2);
+ v->uv_rate_limit = $2;
+ }
+ | RATE_LIMIT {
+
+ warn("Expected number after rate_limit keyword");
+
+ }
+ | BOUNDARY bound {
+
+ struct vif_acl *v_acl;
+
+ v_acl = (struct vif_acl *)malloc(sizeof(struct vif_acl));
+ if (v_acl == NULL)
+ fatal("out of memory");
+ VAL_TO_MASK(v_acl->acl_mask, $2.mask);
+ v_acl->acl_addr = $2.addr & v_acl->acl_mask;
+ if ($2.addr & ~v_acl->acl_mask)
+ warn("Boundary spec %s/%d has host bits set",
+ inet_fmt($2.addr,s1),$2.mask);
+ v_acl->acl_next = v->uv_acl;
+ v->uv_acl = v_acl;
+
+ }
+ | BOUNDARY {
+
+ warn("Expected boundary spec after boundary keyword");
+
+ }
+ ;
+
+interface : ADDR { $$ = $1; }
+ | STRING {
+ $$ = valid_if($1);
+ if ($$ == 0)
+ fatal("Invalid interface name %s",$1);
+ }
+ ;
+
+bound : boundary { $$ = $1; }
+ | STRING { int i;
+
+ for (i=0; i < numbounds; i++) {
+ if (!strcmp(boundlist[i].name, $1)) {
+ $$ = boundlist[i].bound;
+ break;
+ }
+ }
+ if (i == numbounds) {
+ fatal("Invalid boundary name %s",$1);
+ }
+ }
+ ;
+
+boundary : ADDRMASK {
+
+ if ((ntohl($1.addr) & 0xff000000) != 0xef000000) {
+ fatal("Boundaries must be 239.x.x.x, not %s/%d",
+ inet_fmt($1.addr, s1), $1.mask);
+ }
+ $$ = $1;
+
+ }
+ ;
+
+addrmask : ADDRMASK { $$ = $1; }
+ | ADDR { $$.addr = $1; $$.mask = 0; }
+ ;
+%%
+#ifdef __STDC__
+static void
+fatal(char *fmt, ...)
+{
+ va_list ap;
+ char buf[200];
+
+ va_start(ap, fmt);
+#else
+/*VARARGS1*/
+static void
+fatal(fmt, va_alist)
+char *fmt;
+va_dcl
+{
+ va_list ap;
+ char buf[200];
+
+ va_start(ap);
+#endif
+ vsprintf(buf, fmt, ap);
+ va_end(ap);
+
+ log(LOG_ERR,0,"%s: %s near line %d", configfilename, buf, lineno);
+}
+
+#ifdef __STDC__
+static void
+warn(char *fmt, ...)
+{
+ va_list ap;
+ char buf[200];
+
+ va_start(ap, fmt);
+#else
+/*VARARGS1*/
+static void
+warn(fmt, va_alist)
+char *fmt;
+va_dcl
+{
+ va_list ap;
+ char buf[200];
+
+ va_start(ap);
+#endif
+ vsprintf(buf, fmt, ap);
+ va_end(ap);
+
+ log(LOG_WARNING,0,"%s: %s near line %d", configfilename, buf, lineno);
+}
+
+static void
+yyerror(s)
+char *s;
+{
+ log(LOG_ERR, 0, "%s: %s near line %d", configfilename, s, lineno);
+}
+
+static char *
+next_word()
+{
+ static char buf[1024];
+ static char *p=NULL;
+ extern FILE *f;
+ char *q;
+
+ while (1) {
+ if (!p || !*p) {
+ lineno++;
+ if (fgets(buf, sizeof(buf), f) == NULL)
+ return NULL;
+ p = buf;
+ }
+ while (*p && (*p == ' ' || *p == '\t')) /* skip whitespace */
+ p++;
+ if (*p == '#') {
+ p = NULL; /* skip comments */
+ continue;
+ }
+ q = p;
+ while (*p && *p != ' ' && *p != '\t' && *p != '\n')
+ p++; /* find next whitespace */
+ *p++ = '\0'; /* null-terminate string */
+
+ if (!*q) {
+ p = NULL;
+ continue; /* if 0-length string, read another line */
+ }
+
+ return q;
+ }
+}
+
+static int
+yylex()
+{
+ int n;
+ u_int32 addr;
+ char *q;
+
+ if ((q = next_word()) == NULL) {
+ return 0;
+ }
+
+ if (!strcmp(q,"cache_lifetime"))
+ return CACHE_LIFETIME;
+ if (!strcmp(q,"pruning"))
+ return PRUNING;
+ if (!strcmp(q,"phyint"))
+ return PHYINT;
+ if (!strcmp(q,"tunnel"))
+ return TUNNEL;
+ if (!strcmp(q,"disable"))
+ return DISABLE;
+ if (!strcmp(q,"metric"))
+ return METRIC;
+ if (!strcmp(q,"threshold"))
+ return THRESHOLD;
+ if (!strcmp(q,"rate_limit"))
+ return RATE_LIMIT;
+ if (!strcmp(q,"srcrt") || !strcmp(q,"sourceroute"))
+ return SRCRT;
+ if (!strcmp(q,"boundary"))
+ return BOUNDARY;
+ if (!strcmp(q,"netmask"))
+ return NETMASK;
+ if (!strcmp(q,"name"))
+ return NAME;
+ if (!strcmp(q,"altnet"))
+ return ALTNET;
+ if (!strcmp(q,"on") || !strcmp(q,"yes")) {
+ yylval.num = 1;
+ return BOOLEAN;
+ }
+ if (!strcmp(q,"off") || !strcmp(q,"no")) {
+ yylval.num = 0;
+ return BOOLEAN;
+ }
+ if (sscanf(q,"%[.0-9]/%d%c",s1,&n,s2) == 2) {
+ if ((addr = inet_parse(s1)) != 0xffffffff) {
+ yylval.addrmask.mask = n;
+ yylval.addrmask.addr = addr;
+ return ADDRMASK;
+ }
+ /* fall through to returning STRING */
+ }
+ if (sscanf(q,"%[.0-9]%c",s1,s2) == 1) {
+ if ((addr = inet_parse(s1)) != 0xffffffff &&
+ inet_valid_host(addr)) {
+ yylval.addr = addr;
+ return ADDR;
+ }
+ }
+ if (sscanf(q,"0x%8x%c",&n,s1) == 1) {
+ yylval.addr = n;
+ return ADDR;
+ }
+ if (sscanf(q,"%d%c",&n,s1) == 1) {
+ yylval.num = n;
+ return NUMBER;
+ }
+ yylval.ptr = q;
+ return STRING;
+}
+
+void
+config_vifs_from_file()
+{
+ extern FILE *f;
+
+ order = 0;
+ numbounds = 0;
+ lineno = 0;
+
+ if ((f = fopen(configfilename, "r")) == NULL) {
+ if (errno != ENOENT)
+ log(LOG_ERR, errno, "can't open %s", configfilename);
+ return;
+ }
+
+ ifc.ifc_buf = (char *)ifbuf;
+ ifc.ifc_len = sizeof(ifbuf);
+ if (ioctl(udp_socket, SIOCGIFCONF, (char *)&ifc) < 0)
+ log(LOG_ERR, errno, "ioctl SIOCGIFCONF");
+
+ yyparse();
+
+ fclose(f);
+}
+
+static u_int32
+valid_if(s)
+char *s;
+{
+ register vifi_t vifi;
+ register struct uvif *v;
+
+ for (vifi=0, v=uvifs; vifi<numvifs; vifi++, v++)
+ if (!strcmp(v->uv_name, s))
+ return v->uv_lcl_addr;
+
+ return 0;
+}
+
+static struct ifreq *
+ifconfaddr(ifcp, a)
+ struct ifconf *ifcp;
+ u_int32 a;
+{
+ int n;
+ struct ifreq *ifrp = (struct ifreq *)ifcp->ifc_buf;
+ struct ifreq *ifend = (struct ifreq *)((char *)ifrp + ifcp->ifc_len);
+
+ while (ifrp < ifend) {
+ if (ifrp->ifr_addr.sa_family == AF_INET &&
+ ((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr == a)
+ return (ifrp);
+#if (defined(BSD) && (BSD >= 199006))
+ n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
+ if (n < sizeof(*ifrp))
+ ++ifrp;
+ else
+ ifrp = (struct ifreq *)((char *)ifrp + n);
+#else
+ ++ifrp;
+#endif
+ }
+ return (0);
+}
diff --git a/usr.sbin/mrouted/mtrace.8 b/usr.sbin/mrouted/mtrace.8
new file mode 100644
index 0000000000000..c4ac21866af70
--- /dev/null
+++ b/usr.sbin/mrouted/mtrace.8
@@ -0,0 +1,498 @@
+.\" Copyright (c) 1995 by the University of Southern California
+.\" All rights reserved.
+.\"
+.\" Permission to use, copy, modify, and distribute this software and its
+.\" documentation in source and binary forms for non-commercial purposes
+.\" and without fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both the copyright notice and
+.\" this permission notice appear in supporting documentation, and that
+.\" any documentation, advertising materials, and other materials related
+.\" to such distribution and use acknowledge that the software was
+.\" developed by the University of Southern California, Information
+.\" Sciences Institute. The name of the University may not be used to
+.\" endorse or promote products derived from this software without
+.\" specific prior written permission.
+.\"
+.\" THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
+.\" the suitability of this software for any purpose. THIS SOFTWARE IS
+.\" PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+.\" INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" Other copyrights might apply to parts of this software and are so
+.\" noted when applicable.
+.\"
+.\" This manual page (but not the software) was derived from the
+.\" manual page for the traceroute program which bears the following
+.\" copyright notice:
+.\"
+.\" Copyright (c) 1988 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" $Id: mtrace.8,v 3.6 1995/06/25 19:14:07 fenner Exp $
+.\"
+.TH MTRACE 8 "May 8, 1995"
+.UC 6
+.SH NAME
+mtrace \- print multicast path from a source to a receiver
+.SH SYNOPSIS
+.B mtrace
+[
+.B \-g
+.I gateway
+] [
+.B \-i
+.I if_addr
+] [
+.B \-l
+] [
+.B \-M
+] [
+.B \-m
+.I max_hops
+] [
+.B \-n
+] [
+.B \-p
+] [
+.B \-q
+.I nqueries
+] [
+.B \-r
+.I resp_dest
+] [
+.B \-s
+] [
+.B \-t
+.I ttl
+] [
+.B \-w
+.I waittime
+]
+.I source
+[
+.I receiver
+] [
+.I group
+]
+.SH DESCRIPTION
+Assessing problems in the distribution of IP multicast traffic
+can be difficult.
+.B mtrace
+utilizes a tracing feature implemented in multicast routers
+.RB ( mrouted
+version 3.3 and later) that is
+accessed via an extension to the IGMP protocol. A trace query is
+passed hop-by-hop along the reverse path from the
+.I receiver
+to the
+.IR source ,
+collecting hop addresses, packet counts, and routing error conditions
+along the path, and then the response is returned to the requestor.
+.PP
+The only required parameter is the
+.I source
+host name or address. The default
+.I receiver
+is the host running mtrace, and the default
+.I group
+is "MBone Audio" (224.2.0.1), which is sufficient if packet loss
+statistics for a particular multicast group are not needed. These two
+optional parameters may be specified to test the path to some other
+receiver in a particular group, subject to some constraints as
+detailed below. The two parameters can be distinguished because the
+.I receiver
+is a unicast address and the
+.I group
+is a multicast address.
+.SH OPTIONS
+.TP 8 8
+.BI \-g\ gwy
+Send the trace query via unicast directly to the multicast router
+.I gwy
+rather than multicasting the query.
+This must be the last-hop router on the path from the intended
+.I source
+to the
+.IR receiver .
+.RS 8
+.TP 12 12
+.I CAUTION!!
+Version 3.3 of
+.B mrouted
+will crash if a trace query is received via a
+unicast packet and
+.B mrouted
+has no route for the
+.I source
+address. Therefore, do not use the
+.B \-g
+option unless the target
+.B mrouted
+has been verified to be newer than 3.3.
+.RE
+.TP 8 8
+.BI \-i\ addr
+Use
+.I addr
+as the local interface address (on a multi-homed host) for sending the
+trace query and as the default for the
+.I receiver
+and the response destination.
+.TP 8 8
+.B \-l
+Loop indefinitely printing packet rate and loss statistics for the
+multicast path every 10 seconds.
+.TP 8 8
+.B \-M
+Always send the response using multicast rather than attempting
+unicast first.
+.TP 8 8
+.BI \-m\ n
+Set to
+.I n
+the maximum number of hops that will be traced from the
+.I receiver
+back toward the
+.IR source .
+The default is 32 hops (infinity for the DVMRP routing protocol).
+.TP 8 8
+.B \-n
+Print hop addresses numerically rather than symbolically and numerically
+(saves a nameserver address-to-name lookup for each router found on the
+path).
+.TP 8 8
+.BI \-q\ n
+Set the maximum number of query attempts for any hop to
+.IR n .
+The default is 3.
+.TP 8 8
+.B \-p
+Listen passively for multicast responses from traces initiated by
+others (not implemented yet).
+.TP 8 8
+.BI \-r\ host
+Send the trace response to
+.I host
+rather than to the host on which
+.B mtrace
+is being run, or to a multicast address other than the one registered
+for this purpose (224.0.1.32).
+.TP 8 8
+.B \-s
+Print a short form output including only the multicast path and not
+the packet rate and loss statistics.
+.TP 8 8
+.BI \-t\ ttl
+Set the
+.I ttl
+(time-to-live, or number of hops) for multicast trace queries and
+responses. The default is 64, except for local queries to the "all
+routers" multicast group which use ttl 1.
+.TP 8 8
+.BI \-w\ n
+Set the time to wait for a trace response to
+.I n
+seconds (default 3 seconds).
+.SH USAGE
+.SS How It Works
+The technique used by the
+.B traceroute
+tool to trace unicast network paths will not work for IP multicast
+because ICMP responses are specifically forbidden for multicast traffic.
+Instead, a tracing feature has been built into the multicast routers.
+This technique has the advantage that additional information about
+packet rates and losses can be accumulated while the number of packets
+sent is minimized.
+.PP
+Since multicast uses
+reverse path forwarding, the trace is run backwards from the
+.I receiver
+to the
+.IR source .
+A trace query packet is sent to the last
+hop multicast router (the leaf router for the desired
+.I receiver
+address). The last hop router builds a trace response packet, fills in
+a report for its hop, and forwards the trace packet using unicast to
+the router it believes is the previous hop for packets originating
+from the specified
+.IR source .
+Each router along the path adds its report and forwards the packet.
+When the trace response packet reaches the first hop router (the router
+that is directly connected to the source's net), that router sends the
+completed response to the response destination address specified in
+the trace query.
+.PP
+If some multicast router along the path does not implement the
+multicast traceroute feature or if there is some outage, then no
+response will be returned. To solve this problem, the trace query
+includes a maximum hop count field to limit the number of hops traced
+before the response is returned. That allows a partial path to be
+traced.
+.PP
+The reports inserted by each router contain not only the address of
+the hop, but also the ttl required to forward and some flags to indicate
+routing errors, plus counts of the total number of packets on the
+incoming and outgoing interfaces and those forwarded for the specified
+.IR group .
+Taking differences in these counts for two traces separated in time
+and comparing the output packet counts from one hop with the input
+packet counts of the next hop allows the calculation of packet rate
+and packet loss statistics for each hop to isolate congestion
+problems.
+.SS Finding the Last-Hop Router
+The trace query must be sent to the multicast router which is the
+last hop on the path from the
+.I source
+to the
+.IR receiver .
+If the receiver is on the local subnet (as determined using the subnet
+mask), then the default method is to multicast the trace query to
+all-routers.mcast.net (224.0.0.2) with a ttl of 1. Otherwise, the
+trace query is multicast to the
+.I group
+address since the last hop router will be a member of that group if
+the receiver is. Therefore it is necessary to specify a group that
+the intended receiver has joined. This multicast is sent with a
+default ttl of 64, which may not be sufficient for all cases (changed
+with the
+.B \-t
+option).
+If the last hop router is known, it may also be addressed directly
+using the
+.B \-g
+option). Alternatively, if it is desired to trace a group that the
+receiver has not joined, but it is known that the last-hop router is a
+member of another group, the
+.B \-g
+option may also be used to specify a different multicast address for the
+trace query.
+.PP
+When tracing from a multihomed host or router, the default receiver
+address may not be the desired interface for the path from the source.
+In that case, the desired interface should be specified explicitly as
+the
+.IR receiver .
+.SS Directing the Response
+By default,
+.B mtrace
+first attempts to trace the full reverse path, unless the number of
+hops to trace is explicitly set with the
+.B \-m
+option. If there is no response within a 3 second timeout interval
+(changed with the
+.B \-w
+option), a "*" is printed and the probing switches to hop-by-hop mode.
+Trace queries are issued starting with a maximum hop count of one and
+increasing by one until the full path is traced or no response is
+received. At each hop, multiple probes are sent (default is three,
+changed with
+.B \-q
+option). The first half of the attempts (default is one) are made with
+the unicast address of the host running
+.B mtrace
+as the destination for the response. Since the unicast route may be
+blocked, the remainder of attempts request that the response be
+multicast to mtrace.mcast.net (224.0.1.32) with the ttl set to 32 more
+than what's needed to pass the thresholds seen so far along the path
+to the receiver. For the last quarter of the attempts (default is
+one), the ttl is increased by another 32 each time up to a maximum of
+192. Alternatively, the ttl may be set explicity with the
+.B \-t
+option and/or the initial unicast attempts can be forced to use
+multicast instead with the
+.B \-M
+option. For each attempt, if no response is received within the
+timeout, a "*" is printed. After the specified number of attempts
+have failed,
+.B mtrace
+will try to query the next hop router with a DVMRP_ASK_NEIGHBORS2
+request (as used by the
+.B mrinfo
+program) to see what kind of router it is.
+.SH EXAMPLES
+The output of
+.B mtrace
+is in two sections. The first section is a short listing of the hops
+in the order they are queried, that is, in the reverse of the order
+from the
+.I source
+to the
+.IR receiver .
+For each hop, a line is printed showing the hop number (counted
+negatively to indicate that this is the reverse path); the multicast
+routing protocol (DVMRP, MOSPF, PIM, etc.); the threshold required to
+forward data (to the previous hop in the listing as indicated by the
+up-arrow character); and the cumulative delay for the query to reach
+that hop (valid only if the clocks are synchronized). This first
+section ends with a line showing the round-trip time which measures
+the interval from when the query is issued until the response is
+received, both derived from the local system clock. A sample use and
+output might be:
+.PP
+.nf
+.ft C
+oak.isi.edu 80# mtrace -l caraway.lcs.mit.edu 224.2.0.3
+Mtrace from 18.26.0.170 to 128.9.160.100 via group 224.2.0.3
+Querying full reverse path...
+ 0 oak.isi.edu (128.9.160.100)
+ -1 cub.isi.edu (128.9.160.153) DVMRP thresh^ 1 3 ms
+ -2 la.dart.net (140.173.128.1) DVMRP thresh^ 1 14 ms
+ -3 dc.dart.net (140.173.64.1) DVMRP thresh^ 1 50 ms
+ -4 bbn.dart.net (140.173.32.1) DVMRP thresh^ 1 63 ms
+ -5 mit.dart.net (140.173.48.2) DVMRP thresh^ 1 71 ms
+ -6 caraway.lcs.mit.edu (18.26.0.170)
+Round trip time 124 ms
+.fi
+.PP
+The second section provides a pictorial view of the path in the
+forward direction with data flow indicated by arrows pointing downward
+and the query path indicated by arrows pointing upward. For each hop,
+both the entry and exit addresses of the router are shown if
+different, along with the initial ttl required on the packet in order
+to be forwarded at this hop and the propagation delay across the hop
+assuming that the routers at both ends have synchronized clocks. The
+right half of this section is composed of several columns of
+statistics in two groups. Within each group, the columns are the
+number of packets lost, the number of packets sent, the percentage
+lost, and the average packet rate at each hop. These statistics are
+calculated from differences between traces and from hop to hop as
+explained above. The first group shows the statistics for all traffic
+flowing out the interface at one hop and in the interface at the next
+hop. The second group shows the statistics only for traffic forwarded
+from the specified
+.I source
+to the specified
+.IR group .
+.PP
+These statistics are shown on one or two lines for each hop. Without
+any options, this second section of the output is printed only once,
+approximately 10 seconds after the initial trace. One line is shown
+for each hop showing the statistics over that 10-second period. If
+the
+.B \-l
+option is given, the second section is repeated every 10 seconds and
+two lines are shown for each hop. The first line shows the statistics
+for the last 10 seconds, and the second line shows the cumulative
+statistics over the period since the initial trace, which is 101
+seconds in the example below. The second section of the output is
+omitted if the
+.B \-s
+option is set.
+.ie t \{\
+.ft C
+. ie \w'i'<>\w'm' \{\" looks like this is not proper Courier font
+(If this example is not properly columned with a fixed-width font, get
+.B groff
+and try again.)
+. \}
+.\}
+.PP
+.ft C
+.nf
+Waiting to accumulate statistics... Results after 101 seconds:
+
+ Source Response Dest Packet Statistics For Only For Traffic
+18.26.0.170 128.9.160.100 All Multicast Traffic From 18.26.0.170
+ | __/ rtt 125 ms Lost/Sent = Pct Rate To 224.2.0.3
+ v / hop 65 ms --------------------- ------------------
+18.26.0.144
+140.173.48.2 mit.dart.net
+ | ^ ttl 1 0/6 = --% 0 pps 0/2 = --% 0 pps
+ v | hop 8 ms 1/52 = 2% 0 pps 0/18 = 0% 0 pps
+140.173.48.1
+140.173.32.1 bbn.dart.net
+ | ^ ttl 2 0/6 = --% 0 pps 0/2 = --% 0 pps
+ v | hop 12 ms 1/52 = 2% 0 pps 0/18 = 0% 0 pps
+140.173.32.2
+140.173.64.1 dc.dart.net
+ | ^ ttl 3 0/271 = 0% 27 pps 0/2 = --% 0 pps
+ v | hop 34 ms -1/2652 = 0% 26 pps 0/18 = 0% 0 pps
+140.173.64.2
+140.173.128.1 la.dart.net
+ | ^ ttl 4 -2/831 = 0% 83 pps 0/2 = --% 0 pps
+ v | hop 11 ms -3/8072 = 0% 79 pps 0/18 = 0% 0 pps
+140.173.128.2
+128.9.160.153 cub.isi.edu
+ | \\__ ttl 5 833 83 pps 2 0 pps
+ v \\ hop -8 ms 8075 79 pps 18 0 pps
+128.9.160.100 128.9.160.100
+ Receiver Query Source
+.fi
+.PP
+Because the packet counts may be changing as the trace query is
+propagating, there may be small errors (off by 1 or 2) in these
+statistics. However, those errors should not accumulate, so the
+cumulative statistics line should increase in accuracy as a new trace
+is run every 10 seconds. There are two sources of larger errors, both
+of which show up as negative losses:
+.LP
+.RS
+.PD 0
+.TP 3
+\(bu
+If the input to a node is from a multi-access network with more than
+one other node attached, then the input count will be (close to) the
+sum of the output counts from all the attached nodes, but the output
+count from the previous hop on the traced path will be only part of
+that. Hence the output count minus the input count will be negative.
+.TP 3
+\(bu
+In release 3.3 of the DVMRP multicast forwarding software for SunOS
+and other systems, a multicast packet generated on a router will be
+counted as having come in an interface even though it did not. This
+creates the negative loss that can be seen in the example above.
+.PD
+.RE
+.LP
+Note that these negative losses may mask positive losses.
+.PP
+In the example, there is also one negative hop time. This simply
+indicates a lack of synchronization between the system clocks across
+that hop. This example also illustrates how the percentage loss is
+shown as two dashes when the number of packets sent is less than 10
+because the percentage would not be statistically valid.
+.PP
+A second example shows a trace to a receiver that is not local; the
+query is sent to the last-hop router with the
+.B \-g
+option. In this example, the trace of the full reverse path resulted
+in no response because there was a node running an old version of
+.B mrouted
+that did not implement the multicast traceroute function, so
+.B mtrace
+switched to hop-by-hop mode. The \*(lqRoute pruned\*(rq error code
+indicates that traffic for group 224.2.143.24 would not be forwarded.
+.PP
+.nf
+.ft C
+oak.isi.edu 108# mtrace -g 140.173.48.2 204.62.246.73 \\
+ butter.lcs.mit.edu 224.2.143.24
+Mtrace from 204.62.246.73 to 18.26.0.151 via group 224.2.143.24
+Querying full reverse path... * switching to hop-by-hop:
+ 0 butter.lcs.mit.edu (18.26.0.151)
+ -1 jam.lcs.mit.edu (18.26.0.144) DVMRP thresh^ 1 33 ms Route pruned
+ -2 bbn.dart.net (140.173.48.1) DVMRP thresh^ 1 36 ms
+ -3 dc.dart.net (140.173.32.2) DVMRP thresh^ 1 44 ms
+ -4 darpa.dart.net (140.173.240.2) DVMRP thresh^ 16 47 ms
+ -5 * * * noc.hpc.org (192.187.8.2) [mrouted 2.2] didn't respond
+Round trip time 95 ms
+.fi
+.SH AUTHOR
+Implemented by Steve Casner based on an initial prototype written by
+Ajit Thyagarajan. The multicast traceroute mechanism was designed by
+Van Jacobson with help from Steve Casner, Steve Deering, Dino
+Farinacci, and Deb Agrawal; it was implemented in
+.B mrouted
+by Ajit Thyagarajan and Bill Fenner. The option syntax and the output
+format of
+.B mtrace
+are modeled after the unicast
+.B traceroute
+program written by Van Jacobson.
+.SH SEE ALSO
+.BR mrouted (8) ,
+.BR mrinfo (8) ,
+.BR map-mbone (8) ,
+.BR traceroute (8)
diff --git a/usr.sbin/mrouted/pathnames.h b/usr.sbin/mrouted/pathnames.h
new file mode 100644
index 0000000000000..22b0019f089d1
--- /dev/null
+++ b/usr.sbin/mrouted/pathnames.h
@@ -0,0 +1,25 @@
+/*
+ * The mrouted program is covered by the license in the accompanying file
+ * named "LICENSE". Use of the mrouted program represents acceptance of
+ * the terms and conditions listed in that file.
+ *
+ * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
+ * Leland Stanford Junior University.
+ *
+ *
+ * $Id: pathnames.h,v 3.6 1995/06/25 19:17:45 fenner Exp $
+ */
+
+#define _PATH_MROUTED_CONF "/etc/mrouted.conf"
+
+#if (defined(BSD) && (BSD >= 199103))
+#define _PATH_MROUTED_PID "/var/run/mrouted.pid"
+#define _PATH_MROUTED_GENID "/var/run/mrouted.genid"
+#define _PATH_MROUTED_DUMP "/var/tmp/mrouted.dump"
+#define _PATH_MROUTED_CACHE "/var/tmp/mrouted.cache"
+#else
+#define _PATH_MROUTED_PID "/etc/mrouted.pid"
+#define _PATH_MROUTED_GENID "/etc/mrouted.genid"
+#define _PATH_MROUTED_DUMP "/usr/tmp/mrouted.dump"
+#define _PATH_MROUTED_CACHE "/usr/tmp/mrouted.cache"
+#endif
diff --git a/usr.sbin/mrouted/rsrr.c b/usr.sbin/mrouted/rsrr.c
new file mode 100644
index 0000000000000..c7bbc892379f6
--- /dev/null
+++ b/usr.sbin/mrouted/rsrr.c
@@ -0,0 +1,498 @@
+/*
+ * Copyright (c) 1993 by the University of Southern California
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation in source and binary forms for non-commercial purposes
+ * and without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both the copyright notice and
+ * this permission notice appear in supporting documentation. and that
+ * any documentation, advertising materials, and other materials related
+ * to such distribution and use acknowledge that the software was
+ * developed by the University of Southern California, Information
+ * Sciences Institute. The name of the University may not be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
+ * the suitability of this software for any purpose. THIS SOFTWARE IS
+ * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Other copyrights might apply to parts of this software and are so
+ * noted when applicable.
+ */
+
+/* RSRR code written by Daniel Zappala, USC Information Sciences Institute,
+ * April 1995.
+ */
+
+/* May 1995 -- Added support for Route Change Notification */
+
+#ifdef RSRR
+
+#include "defs.h"
+#include <sys/param.h>
+#if (defined(BSD) && (BSD >= 199103))
+#include <stddef.h>
+#endif
+
+/* Taken from prune.c */
+/*
+ * checks for scoped multicast addresses
+ */
+#define GET_SCOPE(gt) { \
+ register int _i; \
+ if (((gt)->gt_mcastgrp & 0xff000000) == 0xef000000) \
+ for (_i = 0; _i < numvifs; _i++) \
+ if (scoped_addr(_i, (gt)->gt_mcastgrp)) \
+ VIFM_SET(_i, (gt)->gt_scope); \
+ }
+
+/*
+ * Exported variables.
+ */
+int rsrr_socket; /* interface to reservation protocol */
+
+/*
+ * Global RSRR variables.
+ */
+char rsrr_recv_buf[RSRR_MAX_LEN]; /* RSRR receive buffer */
+char rsrr_send_buf[RSRR_MAX_LEN]; /* RSRR send buffer */
+
+struct sockaddr_un client_addr;
+int client_length = sizeof(client_addr);
+
+
+/*
+ * Procedure definitions needed internally.
+ */
+static void rsrr_accept __P((int recvlen));
+static void rsrr_accept_iq __P((void));
+static int rsrr_accept_rq __P((struct rsrr_rq *route_query, int flags,
+ struct gtable *gt_notify));
+static int rsrr_send __P((int sendlen));
+static void rsrr_cache __P((struct gtable *gt,
+ struct rsrr_rq *route_query));
+
+/* Initialize RSRR socket */
+void
+rsrr_init()
+{
+ int servlen;
+ struct sockaddr_un serv_addr;
+
+ if ((rsrr_socket = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
+ log(LOG_ERR, errno, "Can't create RSRR socket");
+
+ unlink(RSRR_SERV_PATH);
+ bzero((char *) &serv_addr, sizeof(serv_addr));
+ serv_addr.sun_family = AF_UNIX;
+ strcpy(serv_addr.sun_path, RSRR_SERV_PATH);
+#if (defined(BSD) && (BSD >= 199103))
+ servlen = offsetof(struct sockaddr_un, sun_path) +
+ strlen(serv_addr.sun_path);
+ serv_addr.sun_len = servlen;
+#else
+ servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path);
+#endif
+
+ if (bind(rsrr_socket, (struct sockaddr *) &serv_addr, servlen) < 0)
+ log(LOG_ERR, errno, "Can't bind RSRR socket");
+
+ if (register_input_handler(rsrr_socket,rsrr_read) < 0)
+ log(LOG_WARNING, 0, "Couldn't register RSRR as an input handler");
+}
+
+/* Read a message from the RSRR socket */
+void
+rsrr_read(rfd)
+ fd_set *rfd;
+{
+ register int rsrr_recvlen;
+ register int omask;
+
+ bzero((char *) &client_addr, sizeof(client_addr));
+ rsrr_recvlen = recvfrom(rsrr_socket, rsrr_recv_buf, sizeof(rsrr_recv_buf),
+ 0, (struct sockaddr *)&client_addr, &client_length);
+ if (rsrr_recvlen < 0) {
+ if (errno != EINTR)
+ log(LOG_ERR, errno, "RSRR recvfrom");
+ return;
+ }
+ /* Use of omask taken from main() */
+ omask = sigblock(sigmask(SIGALRM));
+ rsrr_accept(rsrr_recvlen);
+ (void)sigsetmask(omask);
+}
+
+/* Accept a message from the reservation protocol and take
+ * appropriate action.
+ */
+static void
+rsrr_accept(recvlen)
+ int recvlen;
+{
+ struct rsrr_header *rsrr;
+ struct rsrr_rq *route_query;
+
+ if (recvlen < RSRR_HEADER_LEN) {
+ log(LOG_WARNING, 0,
+ "Received RSRR packet of %d bytes, which is less than min size",
+ recvlen);
+ return;
+ }
+
+ rsrr = (struct rsrr_header *) rsrr_recv_buf;
+
+ if (rsrr->version > RSRR_MAX_VERSION) {
+ log(LOG_WARNING, 0,
+ "Received RSRR packet version %d, which I don't understand",
+ rsrr->version);
+ return;
+ }
+
+ switch (rsrr->version) {
+ case 1:
+ switch (rsrr->type) {
+ case RSRR_INITIAL_QUERY:
+ /* Send Initial Reply to client */
+ log(LOG_INFO, 0, "Received Initial Query\n");
+ rsrr_accept_iq();
+ break;
+ case RSRR_ROUTE_QUERY:
+ /* Check size */
+ if (recvlen < RSRR_RQ_LEN) {
+ log(LOG_WARNING, 0,
+ "Received Route Query of %d bytes, which is too small",
+ recvlen);
+ break;
+ }
+ /* Get the query */
+ route_query = (struct rsrr_rq *) (rsrr_recv_buf + RSRR_HEADER_LEN);
+ log(LOG_INFO, 0,
+ "Received Route Query for src %s grp %s notification %d",
+ inet_fmt(route_query->source_addr.s_addr, s1),
+ inet_fmt(route_query->dest_addr.s_addr,s2),
+ BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT));
+ /* Send Route Reply to client */
+ rsrr_accept_rq(route_query,rsrr->flags,NULL);
+ break;
+ default:
+ log(LOG_WARNING, 0,
+ "Received RSRR packet type %d, which I don't handle",
+ rsrr->type);
+ break;
+ }
+ break;
+
+ default:
+ log(LOG_WARNING, 0,
+ "Received RSRR packet version %d, which I don't understand",
+ rsrr->version);
+ break;
+ }
+}
+
+/* Send an Initial Reply to the reservation protocol. */
+static void
+rsrr_accept_iq()
+{
+ struct rsrr_header *rsrr;
+ struct rsrr_vif *vif_list;
+ struct uvif *v;
+ int vifi, sendlen;
+
+ /* Check for space. There should be room for plenty of vifs,
+ * but we should check anyway.
+ */
+ if (numvifs > RSRR_MAX_VIFS) {
+ log(LOG_WARNING, 0,
+ "Can't send RSRR Route Reply because %d is too many vifs %d",
+ numvifs);
+ return;
+ }
+
+ /* Set up message */
+ rsrr = (struct rsrr_header *) rsrr_send_buf;
+ rsrr->version = 1;
+ rsrr->type = RSRR_INITIAL_REPLY;
+ rsrr->flags = 0;
+ rsrr->num = numvifs;
+
+ vif_list = (struct rsrr_vif *) (rsrr_send_buf + RSRR_HEADER_LEN);
+
+ /* Include the vif list. */
+ for (vifi=0, v = uvifs; vifi < numvifs; vifi++, v++) {
+ vif_list[vifi].id = vifi;
+ vif_list[vifi].status = 0;
+ if (v->uv_flags & VIFF_DISABLED)
+ BIT_SET(vif_list[vifi].status,RSRR_DISABLED_BIT);
+ vif_list[vifi].threshold = v->uv_threshold;
+ vif_list[vifi].local_addr.s_addr = v->uv_lcl_addr;
+ }
+
+ /* Get the size. */
+ sendlen = RSRR_HEADER_LEN + numvifs*RSRR_VIF_LEN;
+
+ /* Send it. */
+ log(LOG_INFO, 0, "Send RSRR Initial Reply");
+ rsrr_send(sendlen);
+}
+
+/* Send a Route Reply to the reservation protocol. The Route Query
+ * contains the query to which we are responding. The flags contain
+ * the incoming flags from the query or, for route change
+ * notification, the flags that should be set for the reply. The
+ * kernel table entry contains the routing info to use for a route
+ * change notification.
+ */
+static int
+rsrr_accept_rq(route_query,flags,gt_notify)
+ struct rsrr_rq *route_query;
+ int flags;
+ struct gtable *gt_notify;
+{
+ struct rsrr_header *rsrr;
+ struct rsrr_rr *route_reply;
+ struct gtable *gt,local_g;
+ struct rtentry *r;
+ int sendlen,i;
+ u_long mcastgrp;
+
+ /* Set up message */
+ rsrr = (struct rsrr_header *) rsrr_send_buf;
+ rsrr->version = 1;
+ rsrr->type = RSRR_ROUTE_REPLY;
+ rsrr->flags = 0;
+ rsrr->num = 0;
+
+ route_reply = (struct rsrr_rr *) (rsrr_send_buf + RSRR_HEADER_LEN);
+ route_reply->dest_addr.s_addr = route_query->dest_addr.s_addr;
+ route_reply->source_addr.s_addr = route_query->source_addr.s_addr;
+ route_reply->query_id = route_query->query_id;
+
+ /* Blank routing entry for error. */
+ route_reply->in_vif = 0;
+ route_reply->reserved = 0;
+ route_reply->out_vif_bm = 0;
+
+ /* Get the size. */
+ sendlen = RSRR_RR_LEN;
+
+ /* If kernel table entry is defined, then we are sending a Route Reply
+ * due to a Route Change Notification event. Use the kernel table entry
+ * to supply the routing info.
+ */
+ if (gt_notify) {
+ /* Set flags */
+ rsrr->flags = flags;
+ /* Include the routing entry. */
+ route_reply->in_vif = gt_notify->gt_route->rt_parent;
+ route_reply->out_vif_bm = gt_notify->gt_grpmems;
+
+ } else if (find_src_grp(route_query->source_addr.s_addr, 0,
+ route_query->dest_addr.s_addr)) {
+
+ /* Found kernel entry. Code taken from add_table_entry() */
+ gt = gtp ? gtp->gt_gnext : kernel_table;
+
+ /* Include the routing entry. */
+ route_reply->in_vif = gt->gt_route->rt_parent;
+ route_reply->out_vif_bm = gt->gt_grpmems;
+
+ /* Cache reply if using route change notification. */
+ if BIT_TST(flags,RSRR_NOTIFICATION_BIT) {
+ rsrr_cache(gt,route_query);
+ BIT_SET(rsrr->flags,RSRR_NOTIFICATION_BIT);
+ }
+
+ } else {
+ /* No kernel entry; use routing table. */
+ r = determine_route(route_query->source_addr.s_addr);
+
+ if (r != NULL) {
+ /* We need to mimic what will happen if a data packet
+ * is forwarded by multicast routing -- the kernel will
+ * make an upcall and mrouted will install a route in the kernel.
+ * Our outgoing vif bitmap should reflect what that table
+ * will look like. Grab code from add_table_entry().
+ * This is gross, but it's probably better to be accurate.
+ */
+
+ gt = &local_g;
+ mcastgrp = route_query->dest_addr.s_addr;
+
+ gt->gt_mcastgrp = mcastgrp;
+ gt->gt_grpmems = 0;
+ gt->gt_scope = 0;
+ gt->gt_route = r;
+
+ /* obtain the multicast group membership list */
+ for (i = 0; i < numvifs; i++) {
+ if (VIFM_ISSET(i, r->rt_children) &&
+ !(VIFM_ISSET(i, r->rt_leaves)))
+ VIFM_SET(i, gt->gt_grpmems);
+
+ if (VIFM_ISSET(i, r->rt_leaves) && grplst_mem(i, mcastgrp))
+ VIFM_SET(i, gt->gt_grpmems);
+ }
+
+ GET_SCOPE(gt);
+ gt->gt_grpmems &= ~gt->gt_scope;
+
+ /* Include the routing entry. */
+ route_reply->in_vif = gt->gt_route->rt_parent;
+ route_reply->out_vif_bm = gt->gt_grpmems;
+
+ } else {
+ /* Set error bit. */
+ BIT_SET(rsrr->flags,RSRR_ERROR_BIT);
+ }
+ }
+
+ if (gt_notify)
+ log(LOG_INFO, 0, "Route Change: Send RSRR Route Reply");
+
+ else
+ log(LOG_INFO, 0, "Send RSRR Route Reply");
+
+ log(LOG_INFO, 0, "for src %s dst %s in vif %d out vif %d\n",
+ inet_fmt(route_reply->source_addr.s_addr,s1),
+ inet_fmt(route_reply->dest_addr.s_addr,s2),
+ route_reply->in_vif,route_reply->out_vif_bm);
+
+ /* Send it. */
+ return rsrr_send(sendlen);
+}
+
+/* Send an RSRR message. */
+static int
+rsrr_send(sendlen)
+ int sendlen;
+{
+ int error;
+
+ /* Send it. */
+ error = sendto(rsrr_socket, rsrr_send_buf, sendlen, 0,
+ (struct sockaddr *)&client_addr, client_length);
+
+ /* Check for errors. */
+ if (error < 0) {
+ log(LOG_WARNING, errno, "Failed send on RSRR socket");
+ } else if (error != sendlen) {
+ log(LOG_WARNING, 0,
+ "Sent only %d out of %d bytes on RSRR socket\n", error, sendlen);
+ }
+ return error;
+}
+
+/* Cache a message being sent to a client. Currently only used for
+ * caching Route Reply messages for route change notification.
+ */
+static void
+rsrr_cache(gt,route_query)
+ struct gtable *gt;
+ struct rsrr_rq *route_query;
+{
+ struct rsrr_cache *rc, **rcnp;
+ struct rsrr_header *rsrr;
+
+ rsrr = (struct rsrr_header *) rsrr_send_buf;
+
+ rcnp = &gt->gt_rsrr_cache;
+ while ((rc = *rcnp) != NULL) {
+ if ((rc->route_query.source_addr.s_addr ==
+ route_query->source_addr.s_addr) &&
+ (rc->route_query.dest_addr.s_addr ==
+ route_query->dest_addr.s_addr) &&
+ (!strcmp(rc->client_addr.sun_path,client_addr.sun_path))) {
+ /* Cache entry already exists.
+ * Check if route notification bit has been cleared.
+ */
+ if (!BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT)) {
+ /* Delete cache entry. */
+ *rcnp = rc->next;
+ free(rc);
+ } else {
+ /* Update */
+ rc->route_query.query_id = route_query->query_id;
+ log(LOG_DEBUG, 0,
+ "Update cached query id %ld from client %s\n",
+ rc->route_query.query_id, rc->client_addr.sun_path);
+ }
+ return;
+ }
+ rcnp = &rc->next;
+ }
+
+ /* Cache entry doesn't already exist. Create one and insert at
+ * front of list.
+ */
+ rc = (struct rsrr_cache *) malloc(sizeof(struct rsrr_cache));
+ if (rc == NULL)
+ log(LOG_ERR, 0, "ran out of memory");
+ rc->route_query.source_addr.s_addr = route_query->source_addr.s_addr;
+ rc->route_query.dest_addr.s_addr = route_query->dest_addr.s_addr;
+ rc->route_query.query_id = route_query->query_id;
+ strcpy(rc->client_addr.sun_path, client_addr.sun_path);
+ rc->client_length = client_length;
+ rc->next = gt->gt_rsrr_cache;
+ gt->gt_rsrr_cache = rc;
+ log(LOG_DEBUG, 0, "Cached query id %ld from client %s\n",
+ rc->route_query.query_id,rc->client_addr.sun_path);
+}
+
+/* Send all the messages in the cache. Currently this is used to send
+ * all the cached Route Reply messages for route change notification.
+ */
+void
+rsrr_cache_send(gt,notify)
+ struct gtable *gt;
+ int notify;
+{
+ struct rsrr_cache *rc, **rcnp;
+ int flags = 0;
+
+ if (notify)
+ BIT_SET(flags,RSRR_NOTIFICATION_BIT);
+
+ rcnp = &gt->gt_rsrr_cache;
+ while ((rc = *rcnp) != NULL) {
+ if (rsrr_accept_rq(&rc->route_query,flags,gt) < 0) {
+ log(LOG_DEBUG, 0, "Deleting cached query id %ld from client %s\n",
+ rc->route_query.query_id,rc->client_addr.sun_path);
+ /* Delete cache entry. */
+ *rcnp = rc->next;
+ free(rc);
+ } else {
+ rcnp = &rc->next;
+ }
+ }
+}
+
+/* Clean the cache by deleting all entries. */
+void
+rsrr_cache_clean(gt)
+ struct gtable *gt;
+{
+ struct rsrr_cache *rc,*rc_next;
+
+ printf("cleaning cache for group %s\n",inet_fmt(gt->gt_mcastgrp, s1));
+ rc = gt->gt_rsrr_cache;
+ while (rc) {
+ rc_next = rc->next;
+ free(rc);
+ rc = rc_next;
+ }
+ gt->gt_rsrr_cache = NULL;
+}
+
+void
+rsrr_clean()
+{
+ unlink(RSRR_SERV_PATH);
+}
+
+#endif /* RSRR */
diff --git a/usr.sbin/mrouted/rsrr.h b/usr.sbin/mrouted/rsrr.h
new file mode 100644
index 0000000000000..8bc8c91765353
--- /dev/null
+++ b/usr.sbin/mrouted/rsrr.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1993 by the University of Southern California
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation in source and binary forms for non-commercial purposes
+ * and without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both the copyright notice and
+ * this permission notice appear in supporting documentation. and that
+ * any documentation, advertising materials, and other materials related
+ * to such distribution and use acknowledge that the software was
+ * developed by the University of Southern California, Information
+ * Sciences Institute. The name of the University may not be used to
+ * endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about
+ * the suitability of this software for any purpose. THIS SOFTWARE IS
+ * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Other copyrights might apply to parts of this software and are so
+ * noted when applicable.
+ */
+
+#define RSRR_SERV_PATH "/tmp/.rsrr_svr"
+/* Note this needs to be 14 chars for 4.3 BSD compatibility */
+#define RSRR_CLI_PATH "/tmp/.rsrr_cli"
+
+#define RSRR_MAX_LEN 2048
+#define RSRR_HEADER_LEN (sizeof(struct rsrr_header))
+#define RSRR_RQ_LEN (RSRR_HEADER_LEN + sizeof(struct rsrr_rq))
+#define RSRR_RR_LEN (RSRR_HEADER_LEN + sizeof(struct rsrr_rr))
+#define RSRR_VIF_LEN (sizeof(struct rsrr_vif))
+
+/* Current maximum number of vifs. */
+#define RSRR_MAX_VIFS 32
+
+/* Maximum acceptable version */
+#define RSRR_MAX_VERSION 1
+
+/* RSRR message types */
+#define RSRR_ALL_TYPES 0
+#define RSRR_INITIAL_QUERY 1
+#define RSRR_INITIAL_REPLY 2
+#define RSRR_ROUTE_QUERY 3
+#define RSRR_ROUTE_REPLY 4
+
+/* RSRR Initial Reply (Vif) Status bits
+ * Each definition represents the position of the bit from right to left.
+ *
+ * Right-most bit is the disabled bit, set if the vif is administratively
+ * disabled.
+ */
+#define RSRR_DISABLED_BIT 0
+/* All other bits are zeroes */
+
+/* RSRR Route Query/Reply flag bits
+ * Each definition represents the position of the bit from right to left.
+ *
+ * Right-most bit is the Route Change Notification bit, set if the
+ * reservation protocol wishes to receive notification of
+ * a route change for the source-destination pair listed in the query.
+ * Notification is in the form of an unsolicitied Route Reply.
+ */
+#define RSRR_NOTIFICATION_BIT 0
+/* Next bit indicates an error returning the Route Reply. */
+#define RSRR_ERROR_BIT 1
+/* All other bits are zeroes */
+
+/* Definition of an RSRR message header.
+ * An Initial Query uses only the header, and an Initial Reply uses
+ * the header and a list of vifs.
+ */
+struct rsrr_header {
+ u_char version; /* RSRR Version, currently 1 */
+ u_char type; /* type of message, as defined above */
+ u_char flags; /* flags; defined by type */
+ u_char num; /* number; defined by type */
+};
+
+/* Definition of a vif as seen by the reservation protocol.
+ *
+ * Routing gives the reservation protocol a list of vifs in the
+ * Initial Reply.
+ *
+ * We explicitly list the ID because we can't assume that all routing
+ * protocols will use the same numbering scheme.
+ *
+ * The status is a bitmask of status flags, as defined above. It is the
+ * responsibility of the reservation protocol to perform any status checks
+ * if it uses the MULTICAST_VIF socket option.
+ *
+ * The threshold indicates the ttl an outgoing packet needs in order to
+ * be forwarded. The reservation protocol must perform this check itself if
+ * it uses the MULTICAST_VIF socket option.
+ *
+ * The local address is the address of the physical interface over which
+ * packets are sent.
+ */
+struct rsrr_vif {
+ u_char id; /* vif id */
+ u_char threshold; /* vif threshold ttl */
+ u_short status; /* vif status bitmask */
+ struct in_addr local_addr; /* vif local address */
+};
+
+/* Definition of an RSRR Route Query.
+ *
+ * The query asks routing for the forwarding entry for a particular
+ * source and destination. The query ID uniquely identifies the query
+ * for the reservation protocol. Thus, the combination of the client's
+ * address and the query ID forms a unique identifier for routing.
+ * Flags are defined above.
+ */
+struct rsrr_rq {
+ struct in_addr dest_addr; /* destination */
+ struct in_addr source_addr; /* source */
+ u_long query_id; /* query ID */
+};
+
+/* Definition of an RSRR Route Reply.
+ *
+ * Routing uses the reply to give the reservation protocol the
+ * forwarding entry for a source-destination pair. Routing copies the
+ * query ID from the query and fills in the incoming vif and a bitmask
+ * of the outgoing vifs.
+ * Flags are defined above.
+ */
+struct rsrr_rr {
+ struct in_addr dest_addr; /* destination */
+ struct in_addr source_addr; /* source */
+ u_long query_id; /* query ID */
+ u_short in_vif; /* incoming vif */
+ u_short reserved; /* reserved */
+ u_long out_vif_bm; /* outgoing vif bitmask */
+};
diff --git a/usr.sbin/mrouted/testrsrr/Makefile b/usr.sbin/mrouted/testrsrr/Makefile
new file mode 100644
index 0000000000000..9e710ff3a55e6
--- /dev/null
+++ b/usr.sbin/mrouted/testrsrr/Makefile
@@ -0,0 +1,14 @@
+# $Id: Makefile,v 1.1 1994/09/08 02:51:37 wollman Exp $
+
+PROG= testrsrr
+
+S= ${.CURDIR}/..
+.PATH: $S
+CFLAGS+= -I$S
+
+SRCS= testrsrr.c
+NOMAN=
+
+install:
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/mrouted/testrsrr/testrsrr.c b/usr.sbin/mrouted/testrsrr/testrsrr.c
new file mode 100644
index 0000000000000..b99b593284f2c
--- /dev/null
+++ b/usr.sbin/mrouted/testrsrr/testrsrr.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 1995 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ */
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <sysexits.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "rsrr.h"
+
+char sunpath[MAXPATHLEN];
+int s;
+
+void exitfn(void) {
+ close(s);
+ unlink(sunpath);
+}
+
+int main(void) {
+ struct sockaddr_un sun;
+ char buf[RSRR_MAX_LEN];
+ struct rsrr_header *rh;
+ struct rsrr_vif *rvp;
+ int i;
+
+ s = socket(PF_LOCAL, SOCK_DGRAM, 0);
+ if (s < 0) {
+ err(EX_OSERR, "socket(PF_LOCAL, SOCK_DGRAM, 0)");
+ }
+
+ sun.sun_family = AF_LOCAL;
+ snprintf(sunpath, sizeof sun.sun_path, "/tmp/testrsrr.%lu",
+ (unsigned long)getpid());
+ strcpy(sun.sun_path, sunpath);
+ sun.sun_len = (offsetof(struct sockaddr_un, sun_path)
+ + strlen(sunpath));
+
+ if (bind(s, (struct sockaddr *)&sun, sun.sun_len) < 0) {
+ err(EX_OSERR, "bind: %s", sunpath);
+ }
+
+ atexit(exitfn); /* clean up if we exit on error */
+
+ strcpy(sun.sun_path, RSRR_SERV_PATH);
+ sun.sun_len = (offsetof(struct sockaddr_un, sun_path)
+ + strlen(sunpath));
+
+ if (connect(s, (struct sockaddr *)&sun, sun.sun_len) < 0) {
+ err(EX_OSERR, "connect: %s", RSRR_SERV_PATH);
+ }
+
+ rh = (struct rsrr_header *)buf;
+ rh->version = RSRR_MAX_VERSION;
+ rh->type = RSRR_INITIAL_QUERY;
+ rh->flags = 0;
+ rh->num = 0;
+
+ if (write(s, rh, sizeof *rh) == (ssize_t)-1) {
+ err(EX_OSERR, "write(initial query)");
+ }
+
+ if (read(s, buf, sizeof buf) == (ssize_t)-1) {
+ err(EX_OSERR, "read(initial reply)");
+ }
+
+ if (rh->version != RSRR_MAX_VERSION) {
+ errx(EX_PROTOCOL, "bad remote version %d", rh->version);
+ }
+
+ if (rh->type != RSRR_INITIAL_REPLY) {
+ errx(EX_PROTOCOL, "remote returned unexpected message type %d",
+ rh->type);
+ }
+
+ if (rh->flags) {
+ printf("confusing flags: %d\n", rh->flags);
+ }
+
+ printf("There are %d vifs configured:\n", rh->num);
+
+ printf(" Vif Thresh Status Local address\n");
+ for(i = 0, rvp = (struct rsrr_vif *)(rh + 1); i < rh->num; i++,rvp++) {
+ printf(" %3d %6d %6d %s\n", rvp->id, rvp->threshold,
+ rvp->status, inet_ntoa(rvp->local_addr));
+ }
+ exit(0);
+}
diff --git a/usr.sbin/named/tools/ndc/Makefile b/usr.sbin/named/tools/ndc/Makefile
new file mode 100644
index 0000000000000..043d510015875
--- /dev/null
+++ b/usr.sbin/named/tools/ndc/Makefile
@@ -0,0 +1,25 @@
+MAN8= ndc.8
+CLEANFILES+=ndc
+
+PIDDIR=/var/run
+INDOT=
+PS=ps
+IOT=IOT
+DESTSBIN=${DESTDIR}${BINDIR}
+
+beforeinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 555 \
+ ndc ${DESTDIR}${BINDIR}
+
+all: ndc
+
+ndc: ndc.sh Makefile
+ sed -e "s|%DESTSBIN%|${DESTSBIN}|" \
+ -e "s|%INDOT%|${INDOT}|" \
+ -e "s|%PIDDIR%|${PIDDIR}|" \
+ -e "s|%PS%|${PS}|" \
+ -e "s|%IOT%|${IOT}|" \
+ < ${.CURDIR}/ndc.sh > ndc
+
+.include "${.CURDIR}/../../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/named/tools/ndc/ndc.8 b/usr.sbin/named/tools/ndc/ndc.8
new file mode 100644
index 0000000000000..46eda3926d511
--- /dev/null
+++ b/usr.sbin/named/tools/ndc/ndc.8
@@ -0,0 +1,127 @@
+.\" Copyright (c) 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.TH NDC 8 "November 27, 1994"
+.UC 5
+.SH NAME
+ndc \- name daemon control interface
+.SH SYNOPSYS
+.B ndc
+.I directive
+[ ... ]
+.SH DESCRIPTION
+This command allows the name server administrator to send various signals
+to the name server, or to restart it. Zero or more directives may be given,
+from the following list:
+.TP
+.B status
+Displays the current status of
+.B named
+as shown by
+.BR ps (1).
+.TP
+.B dumpdb
+Causes
+.B named
+to dump its database and cache to
+.B /var/tmp/named_dump.db
+(uses the INT signal.)
+.TP
+.B reload
+Causes
+.B named
+to check the serial numbers of all primary and secondary zones
+and to reload those that have changed (uses the HUP signal.)
+.TP
+.B stats
+Causes
+.B named
+to dump its statistics to
+.B /var/tmp/named.stats
+(uses the IOT or ABRT signal.)
+.TP
+.B trace
+Causes
+.B named
+to increment its ``tracing level'' by one. Whenever the tracing level
+is nonzero, trace information will be written to
+.BR /var/tmp/named.run .
+Higher tracing levels result in more detailed information.
+(Uses the USR1 signal.)
+.TP
+.B notrace
+Causes
+.B named
+to set its ``tracing level'' to zero, closing
+.B /var/tmp/named.run
+if it is open (uses the USR2 signal.)
+.TP
+.B querylog
+Causes
+.B named
+to toggle the ``query logging'' feature, which while on will result in a
+.BR syslog (3)
+of each incoming query (uses the WINCH signal.) Note that query logging
+consumes quite a lot of log file space. This directive may also be given as
+.BR qrylog .
+.TP
+.B start
+Causes
+.B named
+to be started, as long as it isn't already running.
+.TP
+.B stop
+Causes
+.B named
+to be stopped, if it is running.
+.TP
+.B restart
+Causes
+.B named
+to be killed and restarted.
+.SH BUGS
+Arguments to
+.B named
+are not preserved by
+.BR restart ,
+or known by
+.BR start .
+Some mechanism for controlling the parameters and environment should exist.
+.PP
+Implemented as a
+.BR sh (1)
+script.
+.SH AUTHOR
+Paul Vixie (Internet Software Consortium)
+.SH SEE ALSO
+named(8),
+named.reload(8),
+named.restart(8)
diff --git a/usr.sbin/named/tools/ndc/ndc.sh b/usr.sbin/named/tools/ndc/ndc.sh
new file mode 100644
index 0000000000000..b258d202c61dc
--- /dev/null
+++ b/usr.sbin/named/tools/ndc/ndc.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+USAGE='echo \
+ "usage: $0 \
+ (status|dumpdb|reload|stats|trace|notrace|querylog|start|stop|restart) \
+ ... \
+ "; exit 1'
+
+PATH=%DESTSBIN%:/bin:/usr/bin:/usr/ucb:$PATH
+PIDFILE=%PIDDIR%/named.pid
+
+[ -f $PIDFILE ] || {
+ echo "$0: $PIDFILE does not exist"
+ exit 1
+}
+PID=`cat $PIDFILE`
+PS=`%PS% $PID | tail -1 | grep $PID`
+RUNNING=1
+[ `echo $PS | wc -w` -ne 0 ] || {
+ PS="named (pid $PID?) not running"
+ RUNNING=0
+}
+
+for ARG
+do
+ case $ARG in
+ start|stop|restart)
+ ;;
+ *)
+ [ $RUNNING -eq 0 ] && {
+ echo $PS
+ exit 1
+ }
+ esac
+
+ case $ARG in
+ status) echo "$PS";;
+ dumpdb) kill -INT $PID && echo Dumping Database;;
+ reload) kill -HUP $PID && echo Reloading Database;;
+ stats) kill -%IOT% $PID && echo Dumping Statistics;;
+ trace) kill -USR1 $PID && echo Trace Level Incremented;;
+ notrace) kill -USR2 $PID && echo Tracing Cleared;;
+ querylog|qrylog) kill -WINCH $PID && echo Query Logging Toggled;;
+ start)
+ [ $RUNNING -eq 1 ] && {
+ echo "$0: start: named (pid $PID) already running"
+ continue
+ }
+ # If there is a global system configuration file, suck it in.
+ if [ -f /etc/sysconfig ]; then
+ . /etc/sysconfig
+ fi
+ # $namedflags is imported from /etc/sysconfig
+ if [ "X${namedflags}" != "XNO" ]; then
+ %INDOT%named ${namedflags} && echo Name Server Started
+ fi
+ ;;
+ stop)
+ [ $RUNNING -eq 0 ] && {
+ echo "$0: stop: named not running"
+ continue
+ }
+ kill $PID && {
+ sleep 5
+ echo Name Server Stopped
+ }
+ ;;
+ restart)
+ [ $RUNNING -eq 1 ] && {
+ kill $PID && sleep 5
+ }
+ # If there is a global system configuration file, suck it in.
+ if [ -f /etc/sysconfig ]; then
+ . /etc/sysconfig
+ fi
+ # $namedflags is imported from /etc/sysconfig
+ if [ "X${namedflags}" != "XNO" ]; then
+ %INDOT%named ${namedflags} && echo Name Server Restarted
+ fi
+ ;;
+ *) eval "$USAGE";;
+ esac
+done
+test -z "$ARG" && eval "$USAGE"
+
+exit 0
diff --git a/usr.sbin/pkg_install/lib/ftp.c b/usr.sbin/pkg_install/lib/ftp.c
new file mode 100644
index 0000000000000..7b78ee4c97543
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/ftp.c
@@ -0,0 +1,424 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ * $Id: ftp.c,v 1.2 1995/07/31 02:27:58 jkh Exp $
+ *
+ * Return values have been sanitized:
+ * -1 error, but you (still) have a session.
+ * -2 error, your session is dead.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include "ftp.h"
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/* Handy global for us to stick the port # */
+int FtpPort;
+
+static void
+debug(FTP_t ftp, const char *fmt, ...)
+{
+ char p[BUFSIZ];
+ va_list ap;
+ va_start(ap, fmt);
+ strcpy(p,"LIBFTP: ");
+ (void) vsnprintf(p+strlen(p), sizeof p - strlen(p), fmt, ap);
+ va_end(ap);
+ write(ftp->fd_debug,p,strlen(p));
+}
+
+static int
+writes(int fd, char *s)
+{
+ int i = strlen(s);
+ if (i != write(fd,s,i))
+ return -2;
+ return 0;
+}
+
+static __inline char*
+get_a_line(FTP_t ftp)
+{
+ static char buf[BUFSIZ];
+ int i,j;
+
+ for(i=0;i<BUFSIZ;) {
+ j = read(ftp->fd_ctrl,buf+i,1);
+ if (j != 1)
+ return 0;
+ if (buf[i] == '\r' || buf[i] == '\n') {
+ if (!i)
+ continue;
+ buf[i] = '\0';
+ debug(ftp, "received <%s>\n",buf);
+ return buf;
+ }
+ i++;
+ }
+ return buf;
+}
+
+static int
+get_a_number(FTP_t ftp, char **q)
+{
+ char *p;
+ int i = -1,j;
+
+ while(1) {
+ p = get_a_line(ftp);
+ if (!p)
+ return -2;
+ if (!(isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2])))
+ continue;
+ if (i == -1 && p[3] == '-') {
+ i = strtol(p, 0, 0);
+ continue;
+ }
+ if (p[3] != ' ' && p[3] != '\t')
+ continue;
+ j = strtol(p, 0, 0);
+ if (i == -1) {
+ if (q) *q = p+4;
+ return j;
+ } else if (j == i) {
+ if (q) *q = p+4;
+ return j;
+ }
+ }
+}
+
+static int
+zap(FTP_t ftp)
+{
+ int i;
+
+ i = writes(ftp->fd_ctrl,"QUIT\r\n");
+ debug(ftp, "Zapping ftp connection on %d returns %d\n", ftp->fd_ctrl, i);
+ close(ftp->fd_ctrl); ftp->fd_ctrl = -1;
+ close(ftp->fd_xfer); ftp->fd_xfer = -1;
+ ftp->state = init;
+ return -2;
+}
+
+static int
+botch(FTP_t ftp, char *func, char *state)
+{
+ debug(ftp, "Botch: %s called outside state %s\n",func,state);
+ return -2;
+}
+
+static int
+cmd(FTP_t ftp, const char *fmt, ...)
+{
+ char p[BUFSIZ];
+ int i;
+
+ va_list ap;
+ va_start(ap, fmt);
+ (void) vsnprintf(p, sizeof p, fmt, ap);
+ va_end(ap);
+
+ debug(ftp, "send <%s>\n",p);
+ strcat(p,"\r\n");
+ if (writes(ftp->fd_ctrl,p))
+ return -2;
+ i = get_a_number(ftp,0);
+ return i;
+}
+
+FTP_t
+FtpInit()
+{
+ FTP_t ftp;
+
+ ftp = malloc(sizeof *ftp);
+ if (!ftp)
+ return ftp;
+ memset(ftp, 0, sizeof *ftp);
+ ftp->fd_ctrl = -1;
+ ftp->fd_xfer = -1;
+ ftp->fd_debug = -1;
+ ftp->state = init;
+ return ftp;
+}
+
+void
+FtpDebug(FTP_t ftp, int i)
+{
+ ftp->fd_debug = i;
+}
+
+int
+FtpOpen(FTP_t ftp, char *host, char *user, char *passwd)
+{
+ struct hostent *he = NULL;
+ struct sockaddr_in sin;
+ int s;
+ unsigned long temp;
+ int i;
+
+ if (ftp->state != init)
+ return botch(ftp,"FtpOpen","init");
+
+ if (!user)
+ user = "ftp";
+
+ if (!passwd)
+ passwd = "??@??(FreeBSD:libftp)"; /* XXX */
+
+ debug(ftp, "FtpOpen(ftp, %s, %s, %s)\n", host, user, passwd);
+
+ temp = inet_addr(host);
+ if (temp != INADDR_NONE) {
+ debug(ftp, "Using dotted IP address `%s'\n", host);
+ ftp->addrtype = sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = temp;
+ }
+ else {
+ debug(ftp, "Trying to resolve `%s'\n", host);
+ he = gethostbyname(host);
+ if (!he) {
+ debug(ftp, "Lookup of `%s' failed!\n", host);
+ return zap(ftp);
+ }
+ ftp->addrtype = sin.sin_family = he->h_addrtype;
+ bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);
+ }
+
+ sin.sin_port = htons(FtpPort ? FtpPort : 21);
+
+ if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0)
+ {
+ debug(ftp, "Socket open failed: %s (%i)\n", strerror(errno), errno);
+ return zap(ftp);
+ }
+
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ debug(ftp,"Connection failed: %s (%i)\n", strerror(errno), errno);
+ (void)close(s);
+ return zap(ftp);
+ }
+
+ ftp->fd_ctrl = s;
+
+ debug(ftp, "open (%d)\n",get_a_number(ftp,0));
+
+ i = cmd(ftp,"USER %s",user);
+ if (i >= 300 && i < 400)
+ i = cmd(ftp,"PASS %s",passwd);
+ if (i >= 299 || i < 0) {
+ close(ftp->fd_ctrl); ftp->fd_ctrl = -1;
+ return zap(ftp);
+ }
+ ftp->state = isopen;
+ return 0;
+}
+
+void
+FtpClose(FTP_t ftp)
+{
+ if (ftp->state != init)
+ return;
+
+ if (ftp->state != isopen)
+ botch(ftp,"FtpClose","open or init");
+
+ debug(ftp, "FtpClose(ftp)\n");
+ zap(ftp);
+}
+
+int
+FtpChdir(FTP_t ftp, char *dir)
+{
+ int i;
+ if (ftp->state != isopen)
+ return botch(ftp,"FtpChdir","open");
+ i = cmd(ftp,"CWD %s",dir);
+ if (i < 0)
+ return i;
+ else if (i != 250)
+ return -1;
+ return 0;
+}
+
+int
+FtpGet(FTP_t ftp, char *file)
+{
+ int i,s;
+ char *q;
+ unsigned char addr[64];
+ struct sockaddr_in sin;
+ u_long a;
+
+ debug(ftp, "FtpGet(ftp,%s)\n",file);
+ if (ftp->state != isopen)
+ return botch(ftp,"FtpGet","open");
+ if(ftp->binary) {
+ i = cmd(ftp,"TYPE I");
+ if (i < 0)
+ return zap(ftp);
+ if (i > 299)
+ return -1;
+ } else {
+ return -1;
+ }
+
+ if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0)
+ return zap(ftp);
+
+ if (ftp->passive) {
+ debug(ftp, "send <%s>\n","PASV");
+ if (writes(ftp->fd_ctrl,"PASV\r\n"))
+ return zap(ftp);
+ i = get_a_number(ftp,&q);
+ if (i < 0)
+ return zap(ftp);
+ if (i != 227)
+ return zap(ftp);
+ while (*q && !isdigit(*q))
+ q++;
+ if (!*q)
+ return zap(ftp);
+ q--;
+ for(i=0;i<6;i++) {
+ q++;
+ addr[i] = strtol(q,&q,10);
+ }
+
+ sin.sin_family = ftp->addrtype;
+ bcopy(addr, (char *)&sin.sin_addr, 4);
+ bcopy(addr+4, (char *)&sin.sin_port, 2);
+ debug(ftp, "Opening active socket to %s : %u\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
+
+ debug(ftp, "Connecting to %s:%u\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ (void)close(s);
+ debug(ftp, "connect: %s (%d)\n", strerror(errno), errno);
+ return -1;
+ }
+ ftp->fd_xfer = s;
+ i = cmd(ftp,"RETR %s",file);
+ if (i < 0) {
+ close(s);
+ return zap(ftp);
+ }
+ else if (i > 299) {
+ debug(ftp, "FTP: No such file %s, moving on.\n", file);
+ close(s);
+ return -1;
+ }
+ ftp->state = xfer;
+ return s;
+ } else {
+ i = sizeof sin;
+ getsockname(ftp->fd_ctrl,(struct sockaddr *)&sin,&i);
+ sin.sin_port = 0;
+ i = sizeof sin;
+ if (bind(s,(struct sockaddr *)&sin, i) < 0) {
+ close (s);
+ debug(ftp,"bind failed %d\n",errno);
+ return zap(ftp);
+ }
+ getsockname(s,(struct sockaddr *)&sin,&i);
+ if (listen(s,1) < 0) {
+ close (s);
+ debug(ftp,"listen failed %d\n",errno);
+ return zap(ftp);
+ }
+ a = ntohl(sin.sin_addr.s_addr);
+ i = cmd(ftp,"PORT %d,%d,%d,%d,%d,%d",
+ (a >> 24) & 0xff,
+ (a >> 16) & 0xff,
+ (a >> 8) & 0xff,
+ a & 0xff,
+ (ntohs(sin.sin_port) >> 8) & 0xff,
+ ntohs(sin.sin_port) & 0xff);
+ if (i != 200)
+ return -1;
+ i = cmd(ftp,"RETR %s",file);
+ if (i < 0) {
+ close(s);
+ return zap(ftp);
+ }
+ else if (i > 299) {
+ debug(ftp, "FTP: No such file %s, moving on.\n", file);
+ close(s);
+ return -1;
+ }
+ ftp->fd_xfer = accept(s, 0, 0);
+ if (ftp->fd_xfer < 0) {
+ close(s);
+ return zap(ftp);
+ }
+ ftp->state = xfer;
+ close(s);
+ return(ftp->fd_xfer);
+ }
+}
+
+int
+FtpEOF(FTP_t ftp)
+{
+ int i;
+
+ if (ftp->state != xfer)
+ return botch(ftp,"FtpEOF","xfer");
+ debug(ftp, "FtpEOF(ftp)\n");
+ close(ftp->fd_xfer); ftp->fd_xfer = -1;
+ ftp->state = isopen;
+ i = get_a_number(ftp,0);
+ if (i < 0)
+ return zap(ftp);
+ else if (i != 250 && i != 226)
+ return -1;
+ else
+ return 0;
+}
+
+#ifdef STANDALONE_FTP
+
+/* main.c */
+int
+main(int argc, char **argv)
+{
+ FTP_t ftp;
+ int i;
+ char c;
+
+ ftp = FtpInit();
+ if (!ftp)
+ err(1, "FtpInit()");
+
+ FtpDebug(ftp, 1);
+ i = FtpOpen(ftp, "freefall.cdrom.com", "ftp", "phk-libftp@");
+ FtpBinary(ftp, 1);
+ FtpPassive(ftp, 0);
+ FtpChdir(ftp, "/pub");
+ FtpChdir(ftp, "FreeBSD");
+ i = FtpGet(ftp, "README");
+ while (1 == read(i, &c, 1))
+ putchar(c);
+ FtpEOF(ftp);
+ return 0;
+}
+
+#endif /*STANDALONE_FTP*/
diff --git a/usr.sbin/pkg_install/lib/ftp.h b/usr.sbin/pkg_install/lib/ftp.h
new file mode 100644
index 0000000000000..9275dd4f35c6a
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/ftp.h
@@ -0,0 +1,26 @@
+#ifndef _FTP_H_INCLUDE
+#define _FTP_H_INCLUDE
+
+typedef struct {
+ enum {init, isopen, xfer} state;
+ int fd_ctrl;
+ int fd_xfer;
+ int fd_debug;
+ int binary;
+ int passive;
+ int addrtype;
+ char *host;
+ char *file;
+} *FTP_t;
+
+FTP_t FtpInit();
+int FtpOpen(FTP_t, char *host, char *user, char *passwd);
+#define FtpBinary(ftp,bool) { (ftp)->binary = (bool); }
+#define FtpPassive(ftp,bool) { (ftp)->passive = (bool); }
+int FtpChdir(FTP_t, char *);
+int FtpGet(FTP_t, char *);
+int FtpEOF(FTP_t);
+void FtpClose(FTP_t);
+
+#endif
+/* _FTP_H_INCLUDE */
diff --git a/usr.sbin/sicontrol/Makefile b/usr.sbin/sicontrol/Makefile
new file mode 100644
index 0000000000000..48dab5812dfcf
--- /dev/null
+++ b/usr.sbin/sicontrol/Makefile
@@ -0,0 +1,5 @@
+PROG= sicontrol
+SRCS= sicontrol.c
+MAN8= sicontrol.8
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sicontrol/sicontrol.c b/usr.sbin/sicontrol/sicontrol.c
new file mode 100644
index 0000000000000..0924ee0f1d93c
--- /dev/null
+++ b/usr.sbin/sicontrol/sicontrol.c
@@ -0,0 +1,585 @@
+/*
+ * Device driver for Specialix range (SLXOS) of serial line multiplexors.
+ * SLXOS configuration and debug interface
+ *
+ * Copyright (C) 1990, 1992 Specialix International,
+ * Copyright (C) 1993, Andy Rutter <andy@acronym.co.uk>
+ * Copyright (C) 1995, Peter Wemm <peter@haywire.dialix.com>
+ *
+ * Derived from: SunOS 4.x version
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notices, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Andy Rutter of
+ * Advanced Methods and Tools Ltd. based on original information
+ * from Specialix International.
+ * 4. Neither the name of Advanced Methods and Tools, nor Specialix
+ * International may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE.
+ *
+ * $Id: sicontrol.c,v 1.2 1995/08/14 01:56:17 peter Exp $
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/tty.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <machine/si.h>
+
+struct lv {
+ char *lv_name;
+ int lv_bit;
+} lv[] = {
+ "entry", DBG_ENTRY,
+ "open", DBG_OPEN,
+ "close", DBG_CLOSE,
+ "read", DBG_READ,
+ "write", DBG_WRITE,
+ "param", DBG_PARAM,
+ "modem", DBG_MODEM,
+ "select", DBG_SELECT,
+ "optim", DBG_OPTIM,
+ "intr", DBG_INTR,
+ "start", DBG_START,
+ "lstart", DBG_LSTART,
+ "ioctl", DBG_IOCTL,
+ "fail", DBG_FAIL,
+ "autoboot", DBG_AUTOBOOT,
+ "download", DBG_DOWNLOAD,
+ "drain", DBG_DRAIN,
+ "poll", DBG_POLL,
+ 0, 0
+};
+
+static int alldev = 0;
+int getnum(char *str);
+
+int debug(), rxint(), txint();
+int mstate(), nport();
+int ccb_stat(), tty_stat();
+struct opt {
+ char *o_name;
+ int (*o_func)();
+} opt[] = {
+ "debug", debug,
+ "rxint_throttle", rxint,
+ "int_throttle", txint,
+ "mstate", mstate,
+ "nport", nport,
+ "ccbstat", ccb_stat,
+ "ttystat", tty_stat,
+ 0, 0,
+};
+
+struct stat_list {
+ int (*st_func)();
+} stat_list[] = {
+ mstate,
+ 0
+};
+
+#define U_DEBUG 0
+#define U_TXINT 1
+#define U_RXINT 2
+#define U_MSTATE 3
+#define U_NPORT 4
+#define U_STAT_CCB 5
+#define U_STAT_TTY 6
+#define U_STAT_PORT 7
+
+#define U_MAX 7
+#define U_ALL -1
+char *usage[] = {
+ "debug [[add|del|set debug_levels] | [off]]\n",
+ "int_throttle [newvalue]\n",
+ "rxint_throttle [newvalue]\n",
+ "mstate\n",
+ "nport\n",
+ "ccbstat\n",
+ "ttystat\n",
+ "portstat\n",
+ 0
+};
+
+int ctlfd;
+char *Devname;
+struct si_tcsi tc;
+
+main(argc, argv)
+ char **argv;
+{
+ struct opt *op;
+ int (*func)() = NULL;
+
+ if (argc < 2)
+ prusage(U_ALL, 1);
+ Devname = argv[1];
+ if (strcmp(Devname, "-") == 0) {
+ alldev = 1;
+ } else {
+ sidev_t dev;
+ struct stat st;
+
+ if (strchr(Devname, '/') == NULL) {
+ char *acp = malloc(6 + strlen(Devname));
+ strcpy(acp, "/dev/");
+ strcat(acp, Devname);
+ Devname = acp;
+ }
+ if (stat(Devname, &st) < 0) {
+ fprintf(stderr, "can't stat %s\n", Devname);
+ exit(1);
+ }
+ dev.sid_card = SI_CARD(minor(st.st_rdev));
+ dev.sid_port = SI_PORT(minor(st.st_rdev));
+ tc.tc_dev = dev;
+ }
+ ctlfd = opencontrol();
+ if (argc == 2) {
+ dostat();
+ exit(0);
+ }
+
+ argc--; argv++;
+ for (op = opt; op->o_name; op++) {
+ if (strcmp(argv[1], op->o_name) == 0) {
+ func = op->o_func;
+ break;
+ }
+ }
+ if (func == NULL)
+ prusage(U_ALL, 1);
+
+ argc -= 2;
+ argv += 2;
+ (*func)(argc, argv);
+ exit(0);
+}
+
+opencontrol()
+{
+ int fd;
+
+ fd = open(CONTROLDEV, O_RDWR|O_NDELAY);
+ if (fd < 0) {
+ fprintf(stderr, "open on %s - ", CONTROLDEV);
+ perror("");
+ exit(1);
+ }
+ return(fd);
+}
+
+/*
+ * Print a usage message - this relies on U_DEBUG==0 and U_BOOT==1.
+ * Don't print the DEBUG usage string unless explicity requested.
+ */
+prusage(strn, eflag)
+ int strn, eflag;
+{
+ char **cp;
+
+ if (strn == U_ALL) {
+ fprintf(stderr, "Usage: sicontrol - %s", usage[1]);
+ fprintf(stderr, " sicontrol - %s", usage[2]);
+ fprintf(stderr, " sicontrol devname %s", usage[3]);
+ for (cp = &usage[4]; *cp; cp++)
+ fprintf(stderr, " %s", *cp);
+ }
+ else if (strn >= 0 && strn <= U_MAX)
+ fprintf(stderr, "Usage: sicontrol devname %s", usage[strn]);
+ else
+ fprintf(stderr, "sicontrol: usage ???\n");
+ exit(eflag);
+}
+
+/* print port status */
+dostat()
+{
+ char *av[1], *acp;
+ struct stat_list *stp;
+ struct si_tcsi stc;
+ int (*func)();
+ int donefirst = 0;
+
+ printf("%s: ", alldev ? "ALL" : Devname);
+ acp = malloc(strlen(Devname) + 3);
+ memset(acp, ' ', strlen(Devname));
+ strcat(acp, " ");
+ stc = tc;
+ for (stp = stat_list; stp->st_func != NULL; stp++) {
+ if (donefirst)
+ fputs(acp, stdout);
+ else
+ donefirst++;
+ av[0] = NULL;
+ tc = stc;
+ (*stp->st_func)(-1, av);
+ }
+}
+
+/*
+ * debug
+ * debug [[set|add|del debug_lvls] | [off]]
+ */
+debug(ac, av)
+ char **av;
+{
+ int level, cmd;
+ char *str;
+
+ if (ac > 2)
+ prusage(U_DEBUG, 1);
+ if (alldev) {
+ if (ioctl(ctlfd, TCSIGDBG_ALL, &tc.tc_dbglvl) < 0)
+ Perror("TCSIGDBG_ALL on %s", Devname);
+ } else {
+ if (ioctl(ctlfd, TCSIGDBG_LEVEL, &tc) < 0)
+ Perror("TCSIGDBG_LEVEL on %s", Devname);
+ }
+
+ switch (ac) {
+ case 0:
+ printf("%s: debug levels - ", Devname);
+ prlevels(tc.tc_dbglvl);
+ return;
+ case 1:
+ if (strcmp(av[0], "off") == 0) {
+ tc.tc_dbglvl = 0;
+ break;
+ }
+ prusage(U_DEBUG, 1);
+ /* no return */
+ case 2:
+ level = lvls2bits(av[1]);
+ if (strcmp(av[0], "add") == 0)
+ tc.tc_dbglvl |= level;
+ else if (strcmp(av[0], "del") == 0)
+ tc.tc_dbglvl &= ~level;
+ else if (strcmp(av[0], "set") == 0)
+ tc.tc_dbglvl = level;
+ else
+ prusage(U_DEBUG, 1);
+ }
+ if (alldev) {
+ if (ioctl(ctlfd, TCSISDBG_ALL, &tc.tc_dbglvl) < 0)
+ Perror("TCSISDBG_ALL on %s", Devname);
+ } else {
+ if (ioctl(ctlfd, TCSISDBG_LEVEL, &tc) < 0)
+ Perror("TCSISDBG_LEVEL on %s", Devname);
+ }
+}
+
+rxint(ac, av)
+ char **av;
+{
+ tc.tc_port = 0;
+ switch (ac) {
+ case 0:
+ printf("%s: ", Devname);
+ case -1:
+ if (ioctl(ctlfd, TCSIGRXIT, &tc) < 0)
+ Perror("TCSIGRXIT");
+ printf("RX interrupt throttle: %d msec\n", tc.tc_int*10);
+ break;
+ case 1:
+ tc.tc_int = getnum(av[0]) / 10;
+ if (tc.tc_int == 0)
+ tc.tc_int = 1;
+ if (ioctl(ctlfd, TCSIRXIT, &tc) < 0)
+ Perror("TCSIRXIT on %s at %d msec", Devname, tc.tc_int*10);
+ break;
+ default:
+ prusage(U_RXINT, 1);
+ }
+}
+
+txint(ac, av)
+ char **av;
+{
+
+ tc.tc_port = 0;
+ switch (ac) {
+ case 0:
+ printf("%s: ", Devname);
+ case -1:
+ if (ioctl(ctlfd, TCSIGIT, &tc) < 0)
+ Perror("TCSIGIT");
+ printf("aggregate interrupt throttle: %d\n", tc.tc_int);
+ break;
+ case 1:
+ tc.tc_int = getnum(av[0]);
+ if (ioctl(ctlfd, TCSIIT, &tc) < 0)
+ Perror("TCSIIT on %s at %d", Devname, tc.tc_int);
+ break;
+ default:
+ prusage(U_TXINT, 1);
+ }
+}
+
+onoff(ac, av, cmd, cmdstr, prstr, usage)
+ char **av, *cmdstr, *prstr;
+ int ac, cmd, usage;
+{
+ if (ac > 1)
+ prusage(usage, 1);
+ if (ac == 1) {
+ if (strcmp(av[0], "on") == 0)
+ tc.tc_int = 1;
+ else if (strcmp(av[0], "off") == 0)
+ tc.tc_int = 0;
+ else
+ prusage(usage, 1);
+ } else
+ tc.tc_int = -1;
+ if (ioctl(ctlfd, cmd, &tc) < 0)
+ Perror("%s on %s", cmdstr, Devname);
+ switch (ac) {
+ case 0:
+ printf("%s: ", Devname);
+ case -1:
+ printf("%s ", prstr);
+ if (tc.tc_int)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+}
+
+mstate(ac, av)
+ char **av;
+{
+ u_char state;
+
+ switch (ac) {
+ case 0:
+ printf("%s: ", Devname);
+ case -1:
+ break;
+ default:
+ prusage(U_MSTATE, 1);
+ }
+ if (ioctl(ctlfd, TCSISTATE, &tc) < 0)
+ Perror("TCSISTATE on %s", Devname);
+ printf("modem bits state - (0x%x)", tc.tc_int);
+ if (tc.tc_int & IP_DCD) printf(" DCD");
+ if (tc.tc_int & IP_DTR) printf(" DTR");
+ if (tc.tc_int & IP_RTS) printf(" RTS");
+ printf("\n");
+}
+
+nport(ac, av)
+ char **av;
+{
+ int ports;
+
+ if (ac != 0)
+ prusage(U_NPORT, 1);
+ if (ioctl(ctlfd, TCSIPORTS, &ports) < 0)
+ Perror("TCSIPORTS on %s", Devname);
+ printf("SLXOS: total of %d ports\n", ports);
+}
+
+ccb_stat(ac, av)
+char **av;
+{
+ struct si_pstat sip;
+#define CCB sip.tc_ccb
+
+ if (ac != 0)
+ prusage(U_STAT_CCB);
+ sip.tc_dev = tc.tc_dev;
+ if (ioctl(ctlfd, TCSI_CCB, &sip) < 0)
+ Perror("TCSI_CCB on %s", Devname);
+ printf("%s: ", Devname);
+
+ /* WORD next - Next Channel */
+ /* WORD addr_uart - Uart address */
+ /* WORD module - address of module struct */
+ printf("\tuart_type 0x%x\n", CCB.type); /* BYTE type - Uart type */
+ /* BYTE fill - */
+ printf("\tx_status 0x%x\n", CCB.x_status); /* BYTE x_status - XON / XOFF status */
+ printf("\tc_status 0x%x\n", CCB.c_status); /* BYTE c_status - cooking status */
+ printf("\thi_rxipos 0x%x\n", CCB.hi_rxipos); /* BYTE hi_rxipos - stuff into rx buff */
+ printf("\thi_rxopos 0x%x\n", CCB.hi_rxopos); /* BYTE hi_rxopos - stuff out of rx buffer */
+ printf("\thi_txopos 0x%x\n", CCB.hi_txopos); /* BYTE hi_txopos - Stuff into tx ptr */
+ printf("\thi_txipos 0x%x\n", CCB.hi_txipos); /* BYTE hi_txipos - ditto out */
+ printf("\thi_stat 0x%x\n", CCB.hi_stat); /* BYTE hi_stat - Command register */
+ printf("\tdsr_bit 0x%x\n", CCB.dsr_bit); /* BYTE dsr_bit - Magic bit for DSR */
+ printf("\ttxon 0x%x\n", CCB.txon); /* BYTE txon - TX XON char */
+ printf("\ttxoff 0x%x\n", CCB.txoff); /* BYTE txoff - ditto XOFF */
+ printf("\trxon 0x%x\n", CCB.rxon); /* BYTE rxon - RX XON char */
+ printf("\trxoff 0x%x\n", CCB.rxoff); /* BYTE rxoff - ditto XOFF */
+ printf("\thi_mr1 0x%x\n", CCB.hi_mr1); /* BYTE hi_mr1 - mode 1 image */
+ printf("\thi_mr2 0x%x\n", CCB.hi_mr2); /* BYTE hi_mr2 - mode 2 image */
+ printf("\thi_csr 0x%x\n", CCB.hi_csr); /* BYTE hi_csr - clock register */
+ printf("\thi_op 0x%x\n", CCB.hi_op); /* BYTE hi_op - Op control */
+ printf("\thi_ip 0x%x\n", CCB.hi_ip); /* BYTE hi_ip - Input pins */
+ printf("\thi_state 0x%x\n", CCB.hi_state); /* BYTE hi_state - status */
+ printf("\thi_prtcl 0x%x\n", CCB.hi_prtcl); /* BYTE hi_prtcl - Protocol */
+ printf("\thi_txon 0x%x\n", CCB.hi_txon); /* BYTE hi_txon - host copy tx xon stuff */
+ printf("\thi_txoff 0x%x\n", CCB.hi_txoff); /* BYTE hi_txoff - */
+ printf("\thi_rxon 0x%x\n", CCB.hi_rxon); /* BYTE hi_rxon - */
+ printf("\thi_rxoff 0x%x\n", CCB.hi_rxoff); /* BYTE hi_rxoff - */
+ printf("\tclose_prev 0x%x\n", CCB.close_prev); /* BYTE close_prev - Was channel previously closed */
+ printf("\thi_break 0x%x\n", CCB.hi_break); /* BYTE hi_break - host copy break process */
+ printf("\tbreak_state 0x%x\n", CCB.break_state); /* BYTE break_state - local copy ditto */
+ printf("\thi_mask 0x%x\n", CCB.hi_mask); /* BYTE hi_mask - Mask for CS7 etc. */
+ printf("\tmask_z280 0x%x\n", CCB.mask_z280); /* BYTE mask_z280 - Z280's copy */
+ /* BYTE res[0x60 - 36] - */
+ /* BYTE hi_txbuf[SLXOS_BUFFERSIZE] - */
+ /* BYTE hi_rxbuf[SLXOS_BUFFERSIZE] - */
+ /* BYTE res1[0xA0] - */
+
+}
+
+tty_stat(ac, av)
+char **av;
+{
+ struct si_pstat sip;
+#define TTY sip.tc_tty
+
+ if (ac != 0)
+ prusage(U_STAT_TTY);
+ sip.tc_dev = tc.tc_dev;
+ if (ioctl(ctlfd, TCSI_TTY, &sip) < 0)
+ Perror("TCSI_TTY on %s", Devname);
+ printf("%s: ", Devname);
+
+ printf("\tt_outq.c_cc %d.\n", TTY.t_outq.c_cc); /* struct clist t_outq */
+ printf("\tt_dev 0x%x\n", TTY.t_dev); /* dev_t t_dev */
+ printf("\tt_flags 0x%x\n", TTY.t_flags); /* int t_flags */
+ printf("\tt_state 0x%x\n", TTY.t_state); /* int t_state */
+ printf("\tt_hiwat %d.\n", TTY.t_hiwat); /* short t_hiwat */
+ printf("\tt_lowat %d.\n", TTY.t_lowat); /* short t_lowat */
+ printf("\tt_iflag 0x%x\n", TTY.t_iflag); /* t_iflag */
+ printf("\tt_oflag 0x%x\n", TTY.t_oflag); /* t_oflag */
+ printf("\tt_cflag 0x%x\n", TTY.t_cflag); /* t_cflag */
+ printf("\tt_lflag 0x%x\n", TTY.t_lflag); /* t_lflag */
+ printf("\tt_cc 0x%x\n", TTY.t_cc); /* t_cc */
+ printf("\tt_termios.c_ispeed 0x%x\n", TTY.t_termios.c_ispeed); /* t_termios.c_ispeed */
+ printf("\tt_termios.c_ospeed 0x%x\n", TTY.t_termios.c_ospeed); /* t_termios.c_ospeed */
+
+}
+
+islevel(tk)
+ char *tk;
+{
+ register struct lv *lvp;
+ register char *acp;
+
+ for (acp = tk; *acp; acp++)
+ if (isupper(*acp))
+ *acp = tolower(*acp);
+ for (lvp = lv; lvp->lv_name; lvp++)
+ if (strcmp(lvp->lv_name, tk) == 0)
+ return(lvp->lv_bit);
+ return(0);
+}
+
+/*
+ * Convert a string consisting of tokens separated by white space, commas
+ * or `|' into a bitfield - flag any unrecognised tokens.
+ */
+lvls2bits(str)
+ char *str;
+{
+ int i, bits = 0;
+ int errflag = 0;
+ char token[20];
+
+ while (sscanf(str, "%[^,| \t]", token) == 1) {
+ str += strlen(token);
+ while (isspace(*str) || *str==',' || *str=='|')
+ str++;
+ if (strcmp(token, "all") == 0)
+ return(0xffffffff);
+ if ((i = islevel(token)) == 0) {
+ fprintf(stderr, "sicontrol: unknown token '%s'\n", token);
+ errflag++;
+ } else
+ bits |= i;
+ }
+ if (errflag)
+ exit(1);
+
+ return(bits);
+}
+
+int
+getnum(char *str)
+{
+ int x;
+ register char *acp = str;
+
+ x = 0;
+ while (*acp) {
+ if (!isdigit(*acp)) {
+ error("%s is not a number\n", str);
+ exit(1);
+ }
+ x *= 10;
+ x += (*acp - '0');
+ acp++;
+ }
+ return(x);
+}
+
+prlevels(x)
+ int x;
+{
+ struct lv *lvp;
+
+ switch (x) {
+ case 0:
+ printf("(none)\n");
+ break;
+ case 0xffffffff:
+ printf("all\n");
+ break;
+ default:
+ for (lvp = lv; lvp->lv_name; lvp++)
+ if (x & lvp->lv_bit)
+ printf(" %s", lvp->lv_name);
+ printf("\n");
+ }
+}
+
+/* VARARGS */
+Perror(str, a1, a2, a3, a4, a5)
+ char *str;
+ int a1, a2, a3, a4, a5;
+{
+ fprintf(stderr, str, a1, a2, a3, a4, a5);
+ perror(" ");
+ exit(1);
+}
+
+/* VARARGS */
+error(str, a1, a2, a3, a4, a5)
+ char *str;
+ int a1, a2, a3, a4, a5;
+{
+ fprintf(stderr, str, a1, a2, a3, a4, a5);
+ exit(1);
+}
diff --git a/usr.sbin/spkrtest/spkrtest.8 b/usr.sbin/spkrtest/spkrtest.8
new file mode 100644
index 0000000000000..056e0b4de28a8
--- /dev/null
+++ b/usr.sbin/spkrtest/spkrtest.8
@@ -0,0 +1,32 @@
+.Dd May, 1995
+.Dt SPKRTEST 8
+.Os FreeBSD
+
+.Sh NAME
+.Nm spkrtest
+.Nd test script for the speaker driver
+
+.Sh DESCRIPTION
+.Nm
+is an easy to use test script for the speaker driver.
+
+.Sh FILES
+.Bl -tag -width /dev/speakerxx
+.It Pa /dev/speaker
+speaker device file
+.El
+
+.Sh SEE ALSO
+.Xr spkr 4 ,
+.Xr dialog 1 ,
+.Xr perl 1
+
+.\" only for the record
+.\" .Sh AUTHOR
+.\" Eric S. Raymond <esr@snark.thyrsus.com) June 1990;
+.\" dialog+perl by Wolfram Schneider <wosch@cs.tu-berlin.de>, May 1995
+
+.Sh HISTORY
+The
+.Nm
+script appeared in FreeBSD 1.0
diff --git a/usr.sbin/spkrtest/spkrtest.pl b/usr.sbin/spkrtest/spkrtest.pl
new file mode 100644
index 0000000000000..d0fe260924ad0
--- /dev/null
+++ b/usr.sbin/spkrtest/spkrtest.pl
@@ -0,0 +1,96 @@
+#!/usr/bin/perl
+#
+# Test script for the speaker driver
+#
+# v1.0 by Eric S. Raymond (Feb 1990)
+# v1.1 rightstuff contributed by Eric S. Tiedemann (est@snark.thyrsus.com)
+# v2.0 dialog+perl by Wolfram Schneider <wosch@cs.tu-berlin.de>, May 1995
+#
+# NOTE for iso-* (latin1) fonts: use TERM=cons25-iso8859-1
+#
+
+$title = "
+reveille -- Reveille
+contact -- Contact theme from Close Encounters
+dance -- Lord of the Dance (aka Simple Gifts)
+loony -- Loony Toons theme
+sinister -- standard villain's entrance music
+rightstuff -- a trope from \"The Right Stuff\" score by Bill Conti
+toccata -- opening bars of Bach's Toccata and Fugue in D Minor
+startrek -- opening bars of the theme from Star Trek Classic
+";
+
+$music = "
+reveille -- t255l8c.f.afc~c.f.afc~c.f.afc.f.a..f.~c.f.afc~c.f.afc~c.f.afc~c.f..
+contact -- <cd<a#~<a#>f
+dance -- t240<cfcfgagaa#b#>dc<a#a.~fg.gaa#.agagegc.~cfcfgagaa#b#>dc<a#a.~fg.gga.agfgfgf.
+loony -- t255cf8f8edc<a>~cf8f8edd#e~ce8cdce8cd.<a>c8c8c#def8af8
+sinister -- mst200o2ola.l8bc.~a.~>l2d#
+rightstuff -- olcega.a8f>cd2bgc.c8dee2
+toccata -- msl16oldcd4mll8pcb-agf+4.g4p4<msl16dcd4mll8pa.a+f+4p16g4
+startrek -- l2b.f+.p16a.c+.p l4mn<b.>e8a2mspg+e8c+f+8b2
+";
+
+$checklist = 'dialog \
+--title "Speaker test" \
+--checklist "Please select the melodies you wish to play (space for select)" \
+-1 -1 10 \
+';
+
+
+sub Exit {
+ unlink $tmp if $tmp;
+}
+
+$SIG{'INT'} = $SIG{'HUP'} = $SIG{'TRAP'} = $SIG{'QUIT'} =
+ $SIG{'TERM'} = '&Exit';
+
+
+# make assoc array from variable 'var'
+# 'name -- description' -> $var{$name} = $description
+sub splitconfig {
+ local(*var) = @_;
+ local($t, $name, $description);
+
+ foreach $t (split('\n', $var)) {
+ ($name, $description) = split('--', $t);
+
+ $name =~ s/^\s+//; $name =~ s/\s+$//;
+ $description =~ s/\s+//; $description =~ s/\s+$//;
+
+ $var{$name} = $description if $name && $description;
+ }
+}
+
+&splitconfig(*title);
+&splitconfig(*music);
+
+foreach $e (sort keys %title) {
+ ($t = $title{$e}) =~ s/(\")/\\$1/g; # quote '"'
+ $checklist .= "\"$e\" \"$t\" OFF ";
+}
+
+$tmp = ($ENV{'TMP'} || "/tmp") . "/_spkrtest$$";
+system("$checklist 2> $tmp"); # start dialog
+
+if (!$?) { # not cancel
+ open(SPEAKER, ">/dev/speaker") || die "/dev/speaker: $!\n";
+ select(SPEAKER); $| = 1;
+ select(STDOUT); $| = 1;
+
+ if (! -z $tmp) { # select melod(y/ies)
+ foreach $melody (split($", `cat $tmp`)) {
+ $melody =~ s/^"//; $melody =~ s/"$//;
+ print STDOUT "$title{$melody}\n";
+ print SPEAKER "$music{$melody}";
+ sleep 1;
+ }
+ } else { # use default melody
+ $melody = (sort keys %title)[0];
+ print STDOUT "Use default melody: $title{$melody}\n";
+ print SPEAKER "$music{$melody}";
+ }
+ close SPEAKER;
+}
+
+unlink $tmp;
diff --git a/usr.sbin/tcpdump/tcpdump/print-krb.c b/usr.sbin/tcpdump/tcpdump/print-krb.c
new file mode 100644
index 0000000000000..e5470726f84ab
--- /dev/null
+++ b/usr.sbin/tcpdump/tcpdump/print-krb.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Initial contribution from John Hawkinson (jhawk@mit.edu).
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "$Id$";
+/*
+ "@(#) Header: /afs/sipb/project/tcpdump/src/tcpdump-3.0.2/RCS/print-krb.c,v 1.3 1995/08/16 05:33:27 jhawk Exp ";
+*/
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+const char *c_print(register const u_char *s, register const u_char *ep);
+const u_char *krb4_print_hdr(const u_char *cp);
+void krb4_print(const u_char *cp);
+void krb_print(const u_char *dat, int length);
+
+
+#define AUTH_MSG_KDC_REQUEST 1<<1
+#define AUTH_MSG_KDC_REPLY 2<<1
+#define AUTH_MSG_APPL_REQUEST 3<<1
+#define AUTH_MSG_APPL_REQUEST_MUTUAL 4<<1
+#define AUTH_MSG_ERR_REPLY 5<<1
+#define AUTH_MSG_PRIVATE 6<<1
+#define AUTH_MSG_SAFE 7<<1
+#define AUTH_MSG_APPL_ERR 8<<1
+#define AUTH_MSG_DIE 63<<1
+
+#define KERB_ERR_OK 0
+#define KERB_ERR_NAME_EXP 1
+#define KERB_ERR_SERVICE_EXP 2
+#define KERB_ERR_AUTH_EXP 3
+#define KERB_ERR_PKT_VER 4
+#define KERB_ERR_NAME_MAST_KEY_VER 5
+#define KERB_ERR_SERV_MAST_KEY_VER 6
+#define KERB_ERR_BYTE_ORDER 7
+#define KERB_ERR_PRINCIPAL_UNKNOWN 8
+#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9
+#define KERB_ERR_NULL_KEY 10
+
+struct krb {
+ u_char pvno; /* Protocol Version */
+ u_char type; /* Type+B */
+} ;
+
+static char tstr[] = " [|kerberos]";
+
+static struct token type2str[] = {
+ { AUTH_MSG_KDC_REQUEST, "KDC_REQUEST" },
+ { AUTH_MSG_KDC_REPLY, "KDC_REPLY" },
+ { AUTH_MSG_APPL_REQUEST, "APPL_REQUEST" },
+ { AUTH_MSG_APPL_REQUEST_MUTUAL, "APPL_REQUEST_MUTUAL" },
+ { AUTH_MSG_ERR_REPLY, "ERR_REPLY" },
+ { AUTH_MSG_PRIVATE, "PRIVATE" },
+ { AUTH_MSG_SAFE, "SAFE" },
+ { AUTH_MSG_APPL_ERR, "APPL_ERR" },
+ { AUTH_MSG_DIE, "DIE" },
+ { 0, NULL }
+};
+
+static struct token kerr2str[] = {
+ { KERB_ERR_OK, "OK" },
+ { KERB_ERR_NAME_EXP, "NAME_EXP" },
+ { KERB_ERR_SERVICE_EXP, "SERVICE_EXP" },
+ { KERB_ERR_AUTH_EXP, "AUTH_EXP" },
+ { KERB_ERR_PKT_VER, "PKT_VER" },
+ { KERB_ERR_NAME_MAST_KEY_VER, "NAME_MAST_KEY_VER" },
+ { KERB_ERR_SERV_MAST_KEY_VER, "SERV_MAST_KEY_VER" },
+ { KERB_ERR_BYTE_ORDER, "BYTE_ORDER" },
+ { KERB_ERR_PRINCIPAL_UNKNOWN, "PRINCIPAL_UNKNOWN" },
+ { KERB_ERR_PRINCIPAL_NOT_UNIQUE, "PRINCIPAL_NOT_UNIQUE" },
+ { KERB_ERR_NULL_KEY, "NULL_KEY"},
+ { 0, NULL}
+ };
+
+
+/* little endian (unaligned) to host byte order */
+#define vtohlp(x) ((( ((char*)(x))[0] ) ) | \
+ (( ((char*)(x))[1] ) << 8) | \
+ (( ((char*)(x))[2] ) << 16) | \
+ (( ((char*)(x))[3] ) << 24))
+#define vtohsp(x) ((( ((char*)(x))[0] ) ) | \
+ (( ((char*)(x))[1] ) << 8))
+/* network (big endian) (unaligned) to host byte order */
+#define ntohlp(x) ((( ((char*)(x))[3] ) ) | \
+ (( ((char*)(x))[2] ) << 8) | \
+ (( ((char*)(x))[1] ) << 16) | \
+ (( ((char*)(x))[0] ) << 24))
+#define ntohsp(x) ((( ((char*)(x))[1] ) ) | \
+ (( ((char*)(x))[0] ) << 8))
+
+
+
+const char *
+c_print(register const u_char *s, register const u_char *ep)
+{
+ register u_char c;
+ register int flag;
+
+ flag = 1;
+ while (ep == NULL || s < ep) {
+ c = *s++;
+ if (c == '\0') {
+ flag = 0;
+ break;
+ }
+ if (!isascii(c)) {
+ c = toascii(c);
+ putchar('M');
+ putchar('-');
+ }
+ if (!isprint(c)) {
+ c ^= 0x40; /* DEL to ?, others to alpha */
+ putchar('^');
+ }
+ putchar(c);
+ }
+ if (flag)
+ return NULL;
+ return(s);
+}
+
+
+const u_char *
+krb4_print_hdr(const u_char *cp)
+{
+ cp+=2;
+
+#define TCHECK if (cp >= snapend) goto trunc
+#define PRINT if ((cp=c_print(cp, snapend))==NULL) goto trunc
+
+ TCHECK;
+ PRINT;
+ TCHECK;
+ putchar('.'); PRINT;
+ TCHECK;
+ putchar('@'); PRINT;
+ return(cp);
+
+ trunc:
+ fputs(tstr, stdout);
+ return(NULL);
+
+#undef TCHECK
+#undef PRINT
+}
+
+void krb4_print(const u_char *cp)
+{
+ register const struct krb *kp;
+ u_char type;
+ u_short len;
+
+#define TCHECK if (cp >= snapend) goto trunc
+#define PRINT if ((cp=c_print(cp, snapend))==NULL) goto trunc
+#define ENDIAN (kp->type & 0x01)
+/* ENDIAN is 1 for little, 0 for big */
+
+ kp = (struct krb *)cp;
+
+ if ((&kp->type) >= snapend) {
+ fputs(tstr, stdout);
+ return;
+ }
+
+ type = kp->type & (0xFF << 1);
+
+ printf(" %s %s: ", ENDIAN?"le":"be", tok2str(type2str, NULL, type));
+
+ switch(type) {
+ case AUTH_MSG_KDC_REQUEST:
+ if ((cp=krb4_print_hdr(cp)) == NULL)
+ return;
+ cp+=4; /* ctime */
+ TCHECK;
+ printf(" %dmin ", *cp++ * 5);
+ TCHECK;
+ PRINT;
+ TCHECK;
+ putchar('.'); PRINT;
+ break;
+ case AUTH_MSG_APPL_REQUEST:
+ cp+=2;
+ TCHECK;
+ printf("v%d ", *cp++);
+ TCHECK;
+ PRINT;
+ TCHECK;
+ printf(" (%d)", *cp++);
+ TCHECK;
+ printf(" (%d)", *cp);
+ TCHECK;
+ break;
+ case AUTH_MSG_KDC_REPLY:
+ if ((cp=krb4_print_hdr(cp)) == NULL)
+ return;
+ cp+=10; /* timestamp + n + exp + kvno */
+ TCHECK;
+ len=ENDIAN? vtohsp(cp) : ntohsp(cp);
+ printf(" (%d)", len);
+ TCHECK;
+ break;
+ case AUTH_MSG_ERR_REPLY:
+ if ((cp=krb4_print_hdr(cp)) == NULL)
+ return;
+ cp+=4; /* timestamp */
+ TCHECK;
+ printf(" %s ", tok2str(kerr2str, NULL,
+ ENDIAN? vtohlp(cp) :
+ ntohlp(cp)
+ ));
+ cp+=4;
+ TCHECK;
+ PRINT;
+ break;
+ default:
+ fputs("(unknown)", stdout);
+ break;
+ }
+
+ return;
+trunc:
+ fputs(tstr, stdout);
+#undef TCHECK
+}
+
+void
+krb_print(const u_char *dat, int length)
+{
+ register const struct krb *kp;
+
+ kp = (struct krb *)dat;
+
+ if (dat >= snapend) {
+ fputs(tstr, stdout);
+ return;
+ }
+
+ switch (kp->pvno) {
+ case 1:
+ case 2:
+ case 3:
+ printf(" v%d", kp->pvno);
+ break;
+ case 4:
+ printf(" v%d", kp->pvno);
+ krb4_print((const u_char*)kp);
+ break;
+ case 106:
+ case 107:
+ fputs(" v5", stdout);
+ /* Decode ASN.1 here "someday" */
+ break;
+ }
+ return;
+}
diff --git a/usr.sbin/xntpd/conf/ntp.conf.dcf77 b/usr.sbin/xntpd/conf/ntp.conf.dcf77
new file mode 100644
index 0000000000000..678d719d815c3
--- /dev/null
+++ b/usr.sbin/xntpd/conf/ntp.conf.dcf77
@@ -0,0 +1,19 @@
+#
+# XNTP configuration file (/etc/ntp.conf)
+#
+
+#
+# Server is a Boeder DCF77 receiver
+#
+# Use:
+# 127.127.8.40 for /dev/refclock-0 (/dev/ttyd0)
+# 127.127.8.41 for /dev/refclock-1 (/dev/ttyd1)
+# 127.127.8.42 for /dev/refclock-2 (/dev/ttyd2)
+# 127.127.8.43 for /dev/refclock-3 (/dev/ttyd3)
+#
+server 127.127.8.40
+
+#
+# drift file
+#
+driftfile /etc/ntp.drift