Revert "Remove crunchgen(8)."
authorFrançois Tigeot <ftigeot@wolfpond.org>
Sun, 30 Mar 2014 19:46:42 +0000 (21:46 +0200)
committerFrançois Tigeot <ftigeot@wolfpond.org>
Mon, 31 Mar 2014 06:39:28 +0000 (08:39 +0200)
This reverts commit 97c14704c37c914dbd89b22465a421ffde7fe89d.

Conflicts:
Makefile.inc1
Makefile_upgrade.inc
sbin/ifconfig/Makefile
usr.bin/vi/Makefile
usr.sbin/ppp/bundle.c
usr.sbin/pppd/Makefile
usr.sbin/tcpdump/Makefile

36 files changed:
Makefile.inc1
Makefile_upgrade.inc
sbin/camcontrol/Makefile
sbin/ifconfig/Makefile
sbin/ping/Makefile
usr.bin/Makefile
usr.bin/crunch/COPYRIGHT [new file with mode: 0644]
usr.bin/crunch/Makefile [new file with mode: 0644]
usr.bin/crunch/Makefile.inc [new file with mode: 0644]
usr.bin/crunch/README [new file with mode: 0644]
usr.bin/crunch/crunchgen/Makefile [new file with mode: 0644]
usr.bin/crunch/crunchgen/crunched_main.c [new file with mode: 0644]
usr.bin/crunch/crunchgen/crunchgen.1 [new file with mode: 0644]
usr.bin/crunch/crunchgen/crunchgen.c [new file with mode: 0644]
usr.bin/crunch/crunchgen/mkskel.sh [new file with mode: 0644]
usr.bin/crunch/crunchide/Makefile [new file with mode: 0644]
usr.bin/crunch/crunchide/crunchide.1 [new file with mode: 0644]
usr.bin/crunch/crunchide/crunchide.c [new file with mode: 0644]
usr.bin/crunch/crunchide/exec_aout.c [new file with mode: 0644]
usr.bin/crunch/crunchide/exec_elf32.c [new file with mode: 0644]
usr.bin/crunch/crunchide/exec_elf64.c [new file with mode: 0644]
usr.bin/crunch/crunchide/extern.h [new file with mode: 0644]
usr.bin/crunch/examples/Makefile [new file with mode: 0644]
usr.bin/crunch/examples/filesystem.conf [new file with mode: 0644]
usr.bin/crunch/examples/fixit.conf [new file with mode: 0644]
usr.bin/crunch/examples/kcopy.conf [new file with mode: 0644]
usr.bin/crunch/examples/really-big.conf [new file with mode: 0644]
usr.bin/vi/Makefile
usr.sbin/802_11/wpa_supplicant/Makefile
usr.sbin/inetd/Makefile
usr.sbin/ppp/Makefile
usr.sbin/ppp/bundle.c
usr.sbin/ppp/physical.c
usr.sbin/pppd/Makefile
usr.sbin/sendmail/Makefile
usr.sbin/tcpdump/Makefile

index 8ab7470..0b994bc 100644 (file)
@@ -877,7 +877,9 @@ btools-${_tool}!
 _btxld=        usr.sbin/btxld
 .endif
 
-CTOOLSDIRS= ${_btxld} ${_binutils} usr.bin/objformat ${_gcc_common_cross} \
+CTOOLSDIRS= ${_btxld} ${_binutils} \
+               usr.bin/objformat usr.bin/crunch/crunchide \
+               ${_gcc_common_cross} \
                ${_gcc44_cross} ${_gcc47_cross} ${_custom_cross}
 
 cross-tools: cross-tools-targets
index 76230b4..49ccff3 100644 (file)
@@ -1099,12 +1099,6 @@ TO_REMOVE+=/usr/share/info/cpio.info.gz
 TO_REMOVE+=/usr/sbin/tcpslice
 TO_REMOVE+=/usr/share/man/cat1/tcpslice.1.gz
 TO_REMOVE+=/usr/share/man/man1/tcpslice.1.gz
-TO_REMOVE+=/usr/bin/crunchgen
-TO_REMOVE+=/usr/share/man/cat1/crunchgen.1.gz
-TO_REMOVE+=/usr/share/man/man1/crunchgen.1.gz
-TO_REMOVE+=/usr/bin/crunchide
-TO_REMOVE+=/usr/share/man/cat1/crunchide.1.gz
-TO_REMOVE+=/usr/share/man/man1/crunchide.1.gz
 TO_REMOVE+=/usr/share/man/cat9/suser.9.gz
 TO_REMOVE+=/usr/share/man/man9/suser.9.gz
 TO_REMOVE+=/usr/share/man/cat9/suser_cred.9.gz
index 4308a4d..8425e0c 100644 (file)
@@ -2,10 +2,14 @@
 # $DragonFly: src/sbin/camcontrol/Makefile,v 1.7 2008/03/07 08:44:24 pavalos Exp $
 
 PROG=  camcontrol
-SRCS=  camcontrol.c modeedit.c util.c
-MAN=   camcontrol.8
-
+SRCS=  camcontrol.c util.c
+.if !defined(RELEASE_CRUNCH)
+SRCS+= modeedit.c
+.else
+CFLAGS+= -DMINIMALISTIC
+.endif
 DPADD= ${LIBCAM} ${LIBSBUF} ${LIBUTIL}
 LDADD= -lcam -lsbuf -lutil
+MAN=   camcontrol.8
 
 .include <bsd.prog.mk>
index 85517ab..fe215e4 100644 (file)
@@ -28,10 +28,14 @@ SRCS+=      ifcarp.c                # SIOC[GS]VH support
 
 SRCS+= ifbridge.c              # bridge support
 
+.ifndef RELEASE_CRUNCH
 SRCS+= af_ipx.c                # IPX support
 
 DPADD= ${LIBIPX} ${LIBBSDXML} ${LIBSBUF}
 LDADD= -lipx -lbsdxml -lsbuf
+.else
+CFLAGS+= -DNO_IPX
+.endif
 
 MAN=   ifconfig.8
 
index 7a89eca..c21eba7 100644 (file)
@@ -5,9 +5,13 @@
 PROG=  ping
 MAN=   ping.8
 BINMODE=4555
-DPADD= ${LIBM} ${LIBIPSEC}
-LDADD= -lm -lipsec
+DPADD= ${LIBM}
+LDADD= -lm
 
+.if !defined(RELEASE_CRUNCH)
 CFLAGS+=-DIPSEC
+DPADD+=        ${LIBIPSEC}
+LDADD+=        -lipsec
+.endif
 
 .include <bsd.prog.mk>
index d1a73c2..e8eecb2 100644 (file)
@@ -47,6 +47,7 @@ SUBDIR=       alias \
        compile_et \
        compress \
        cpio \
+       crunch \
        csplit \
        ctags \
        cut \
diff --git a/usr.bin/crunch/COPYRIGHT b/usr.bin/crunch/COPYRIGHT
new file mode 100644 (file)
index 0000000..c7b4d2f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1994 University of Maryland
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: James da Silva, Systems Design and Analysis Group
+ *                        Computer Science Department
+ *                        University of Maryland at College Park
+ */
diff --git a/usr.bin/crunch/Makefile b/usr.bin/crunch/Makefile
new file mode 100644 (file)
index 0000000..a38e0b9
--- /dev/null
@@ -0,0 +1,4 @@
+
+SUBDIR=crunchgen crunchide
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/crunch/Makefile.inc b/usr.bin/crunch/Makefile.inc
new file mode 100644 (file)
index 0000000..ad6e982
--- /dev/null
@@ -0,0 +1,3 @@
+WARNS?=        1
+
+.include "../Makefile.inc"
diff --git a/usr.bin/crunch/README b/usr.bin/crunch/README
new file mode 100644 (file)
index 0000000..27c2d02
--- /dev/null
@@ -0,0 +1,88 @@
+
+CRUNCH 0.2 README                              6/14/94
+
+Crunch is available via anonymous ftp to ftp.cs.umd.edu in
+               pub/bsd/crunch-0.2.tar.gz
+
+
+WHAT'S NEW IN 0.2
+
+* The prototype awk script has been replaced by a more capable and
+  hopefully more robust C program.
+* No fragile template makefiles or dependencies on the details of the
+  bsd build environment.
+* You can build crunched binaries even with no sources on-line, you
+  just need the .o files.  Crunchgen still will try to figure out as
+  much as possible on its own, but you can override its guessing by
+  specifying the list of .o files explicitly.
+* Crunch itself has been bmake'd and some man pages written, so it
+  should be ready to install.
+
+
+INTRODUCTION
+
+Crunch is a little package that helps create "crunched" binaries for use
+on boot, install, and fixit floppies.  A crunched binary in this case is
+one where many programs have been linked together into one a.out file.
+The different programs are run depending on the value of argv[0], so
+hard links to the crunched binary suffice to simulate a perfectly normal
+system.
+
+As an example, I have created an 980K crunched "fixit" binary containing
+the following programs in their entirety:
+
+       cat chmod cp date dd df echo ed expr hostname kill ln ls mkdir
+       mt mv pwd rcp rm rmdir sh sleep stty sync test [ badsect chown
+       clri disklabel dump rdump dmesg fdisk fsck halt ifconfig init
+       mknod mount newfs ping reboot restore rrestore swapon umount
+       ftp rsh sed telnet rlogin vi cpio gzip gunzip gzcat
+
+Note carefully: vi, cpio, gzip, ed, sed, dump/restore, some networking
+utilities, and the disk management utilities, all in a binary small
+enough to fit on a 1.2 MB root filesystem floppy (albeit with the kernel
+on its own boot floppy).  A more reasonable subset can be made to fit
+easily with a kernel for a decent one-disk fixit filesystem.
+
+The linking together of different programs by hand is an old
+space-saving technique.  Crunch automates the process by building the
+necessary stub files and makefile for you (via the crunchgen program),
+and by doctoring the symbol tables of the component .o files to allow
+them to link without "symbol multiply defined" conflicts (via the
+crunchide program).
+
+
+BUILDING CRUNCH
+
+Just type make, then make install.
+
+Crunch was written and tested under NetBSD/i386, but should work under
+other PC BSD systems that use GNU ld.
+
+The crunchgen(1) and crunchide(1) man pages have more details on using
+crunch, and the examples subdirectory contains some working .conf files
+and a sample Makefile.
+
+CREDITS
+
+Thanks to the NetBSD team for a consistently high quality effort in
+bringing together a solid, state of the art development environment.
+
+Thanks to the FreeBSD guys; Rod Grimes, Nate Williams and Jordan
+Hubbard; and to Bruce Evans, for immediate and detailed feedback on
+crunch 0.1, and for pressing me to make the prototype more useable.
+
+Crunch was written for the Maruti Hard Real-Time Operating System
+project at the University of Maryland, to help make for better install
+and recovery procedures for our NetBSD-based development environment. It
+is copyright (c) 1994 by the University of Maryland under a UCB-style
+freely- redistributable notice.  See the file COPYRIGHT for details.
+
+Please let me know of any problems or of enhancements you make to this
+package.  I'm particularly interested in the details of what you found
+was good to put on your fixit or install disks.  Thanks!
+
+Share and Enjoy,
+Jaime
+............................................................................
+: Stand on my shoulders, : jds@cs.umd.edu  :                  James da Silva
+: not on my toes.        : uunet!mimsy!jds : http://www.cs.umd.edu/users/jds
diff --git a/usr.bin/crunch/crunchgen/Makefile b/usr.bin/crunch/crunchgen/Makefile
new file mode 100644 (file)
index 0000000..ecf99d9
--- /dev/null
@@ -0,0 +1,11 @@
+# $FreeBSD: src/usr.sbin/crunch/crunchgen/Makefile,v 1.4.8.1 2002/04/11 19:41:39 murray Exp $
+# $DragonFly: src/usr.sbin/crunch/crunchgen/Makefile,v 1.2 2003/06/17 04:29:53 dillon Exp $
+
+PROG=  crunchgen
+SRCS=  crunchgen.c crunched_skel.c
+CLEANFILES+= crunched_skel.c
+
+crunched_skel.c: crunched_main.c
+       sh -e ${.CURDIR}/mkskel.sh ${.CURDIR}/crunched_main.c >crunched_skel.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/crunch/crunchgen/crunched_main.c b/usr.bin/crunch/crunchgen/crunched_main.c
new file mode 100644 (file)
index 0000000..c3bfe07
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1994 University of Maryland
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: James da Silva, Systems Design and Analysis Group
+ *                        Computer Science Department
+ *                        University of Maryland at College Park
+ *
+ * $FreeBSD: src/usr.sbin/crunch/crunchgen/crunched_main.c,v 1.6.6.2 2002/08/09 02:42:02 gshapiro Exp $
+ * $DragonFly: src/usr.sbin/crunch/crunchgen/crunched_main.c,v 1.3 2003/11/16 14:10:44 eirikn Exp $
+ */
+/*
+ * crunched_main.c - main program for crunched binaries, it branches to a
+ *     particular subprogram based on the value of argv[0].  Also included
+ *     is a little program invoked when the crunched binary is called via
+ *     its EXECNAME.  This one prints out the list of compiled-in binaries,
+ *     or calls one of them based on argv[1].   This allows the testing of
+ *     the crunched binary without creating all the links.
+ */
+#include <stdio.h>
+#include <string.h>
+
+struct stub {
+    char *name;
+    int (*f)();
+};
+
+extern struct stub entry_points[];
+
+int
+main(int argc, char **argv, char **envp)
+{
+    char *slash, *basename;
+    struct stub *ep;
+
+    if(argv[0] == NULL || *argv[0] == '\0')
+       crunched_usage();
+
+    slash = strrchr(argv[0], '/');
+    basename = slash? slash+1 : argv[0];
+
+    for(ep=entry_points; ep->name != NULL; ep++)
+       if(!strcmp(basename, ep->name)) break;
+
+    if(ep->name)
+       return ep->f(argc, argv, envp);
+    else {
+       fprintf(stderr, "%s: %s not compiled in\n", EXECNAME, basename);
+       crunched_usage();
+    }
+}
+
+
+int
+crunched_here(char *path)
+{
+    char *slash, *basename;
+    struct stub *ep;
+
+    slash = strrchr(path, '/');
+    basename = slash? slash+1 : path;
+
+    for(ep=entry_points; ep->name != NULL; ep++)
+       if(!strcmp(basename, ep->name))
+           return 1;
+    return 0;
+}
+
+
+int
+crunched_main(int argc, char **argv, char **envp)
+{
+    struct stub *ep;
+    int columns, len;
+
+    if(argc <= 1)
+       crunched_usage();
+
+    return main(--argc, ++argv, envp);
+}
+
+
+int
+crunched_usage(void)
+{
+    int columns, len;
+    struct stub *ep;
+
+    fprintf(stderr, "usage: %s <prog> <args> ..., where <prog> is one of:\n",
+           EXECNAME);
+    columns = 0;
+    for(ep=entry_points; ep->name != NULL; ep++) {
+       len = strlen(ep->name) + 1;
+       if(columns+len < 80)
+           columns += len;
+       else {
+           fprintf(stderr, "\n");
+           columns = len;
+       }
+       fprintf(stderr, " %s", ep->name);
+    }
+    fprintf(stderr, "\n");
+    exit(1);
+}
+
+/* end of crunched_main.c */
diff --git a/usr.bin/crunch/crunchgen/crunchgen.1 b/usr.bin/crunch/crunchgen/crunchgen.1
new file mode 100644 (file)
index 0000000..de57b15
--- /dev/null
@@ -0,0 +1,447 @@
+.\"
+.\" Copyright (c) 1994 University of Maryland
+.\" All Rights Reserved.
+.\"
+.\" Permission to use, copy, modify, distribute, and sell this software and its
+.\" documentation for any purpose is hereby granted without fee, 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 U.M. not be used in advertising or
+.\" publicity pertaining to distribution of the software without specific,
+.\" written prior permission.  U.M. makes no representations about the
+.\" suitability of this software for any purpose.  It is provided "as is"
+.\" without express or implied warranty.
+.\"
+.\" U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+.\" BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+.\" IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Author: James da Silva, Systems Design and Analysis Group
+.\"                       Computer Science Department
+.\"                       University of Maryland at College Park
+.\" $FreeBSD: src/usr.sbin/crunch/crunchgen/crunchgen.1,v 1.11.2.11 2003/03/12 22:08:13 trhodes Exp $
+.\" $DragonFly: src/usr.sbin/crunch/crunchgen/crunchgen.1,v 1.3 2008/05/02 02:05:07 swildner Exp $
+.\"
+.Dd November 16, 2000
+.Dt CRUNCHGEN 1
+.Os
+.Sh NAME
+.Nm crunchgen
+.Nd generates build environment for a crunched binary
+.Sh SYNOPSIS
+.Bk -words
+.Nm
+.Op Fl foql
+.Op Fl h Ar makefile-header-name
+.Op Fl m Ar makefile-name
+.Op Fl p Ar obj-prefix
+.Op Fl c Ar c-file-name
+.Op Fl e Ar exec-file-name
+.Op Ar conf-file
+.Ek
+.Sh DESCRIPTION
+A crunched binary is a program made up of many other programs linked
+together into a single executable.
+The crunched binary
+.Fn main
+function determines which component program to run by the contents of
+.Va argv[0] .
+The main reason to crunch programs together is for fitting
+as many programs as possible onto an installation or system recovery
+floppy.
+.Pp
+The
+.Nm
+utility reads in the specifications in
+.Ar conf-file
+for a crunched binary, and generates a
+.Pa Makefile
+and accompanying
+top-level C source file that when built creates the crunched executable
+file from the component programs.
+For each component program,
+.Nm
+can optionally attempt to determine the object (.o) files that make up
+the program from its source directory
+.Pa Makefile .
+This information is cached between runs.
+The
+.Nm
+utility uses the companion program
+.Xr crunchide 1
+to eliminate link-time conflicts between the component programs by
+hiding all unnecessary symbols.
+.Pp
+The
+.Nm
+utility places specific requirements on package
+.Pa Makefile Ns s
+which make it unsuitable for use with
+.No non- Ns Bx
+sources.
+In particular, the
+.Pa Makefile
+must contain the target
+.Ic depend ,
+and it must define all object files in the variable
+.Va OBJS .
+In some cases, you can use a fake
+.Pa Makefile :
+before looking for
+.Pa Makefile
+in the source directory
+.Pa foo ,
+.Nm
+looks for the file
+.Pa Makefile.foo
+in the current directory.
+.Pp
+After
+.Nm
+is run, the crunched binary can be built by running
+.Dq Li make -f <conf-name>.mk .
+The component programs' object files must already be built.
+An
+.Ic objs
+target, included in the output makefile, will
+run
+.Xr make 1
+in each component program's source dir to build the object
+files for the user.
+This is not done automatically since in release
+engineering circumstances it is generally not desirable to be
+modifying objects in other directories.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl c Ar c-file-name
+Set output C file name to
+.Ar c-file-name .
+The default name is
+.Pa <conf-name>.c .
+.It Fl e Ar exec-file-name
+Set crunched binary executable file name to
+.Ar exec-file-name .
+The default name is
+.Pa <conf-name> .
+.It Fl f
+Flush cache.
+Forces the recalculation of cached parameters.
+.It Fl l
+List names.
+Lists the names this binary will respond to.
+.It Fl h Ar makefile-header-name
+Set the name of a file to be included at the beginning of the
+.Pa Makefile Ns s
+generated by
+.Nm .
+This is useful to define some make variables such as
+.Va RELEASE_CRUNCH
+or similar, which might affect the behaviour of
+.Xr make 1
+and are annoying to pass through environment variables.
+.It Fl m Ar makefile-name
+Set output
+.Pa Makefile
+name to
+.Ar makefile-name .
+The default name is
+.Pa <conf-name>.mk .
+.It Fl o
+Add
+.Dq Li make obj
+rules to each program make target.
+.It Fl p Ar obj-prefix
+Set the pathname to be prepended to the
+.Ic srcdir
+when computing the
+.Ic objdir .
+If this option is not present, then the prefix used
+is the content of the
+.Ev MAKEOBJDIRPREFIX
+environment variable, or
+.Pa /usr/obj .
+.It Fl q
+Quiet operation.
+Status messages are suppressed.
+.El
+.Sh CRUNCHGEN CONFIGURATION FILE COMMANDS
+The
+.Nm
+utility reads specifications from the
+.Ar conf-file
+that describe the components of the crunched binary.
+In its simplest
+use, the component program names are merely listed along with the
+top-level source directories in which their sources can be found.
+The
+.Nm
+utility then calculates (via the source makefiles) and caches the
+list of object files and their locations.
+For more specialized
+situations, the user can specify by hand all the parameters that
+.Nm
+needs.
+.Pp
+The
+.Ar conf-file
+commands are as follows:
+.Bl -tag -width indent
+.It Ic srcdirs Ar dirname ...
+A list of source trees in which the source directories of the
+component programs can be found.
+These dirs are searched using the
+.Bx
+.Dq Pa <source-dir>/<progname>/
+convention.
+Multiple
+.Ic srcdirs
+lines can be specified.
+The directories are searched in the order they are given.
+.It Ic progs Ar progname ...
+A list of programs that make up the crunched binary.
+Multiple
+.Ic progs
+lines can be specified.
+.It Ic libs Ar libspec ...
+A list of library specifications to be included in the crunched binary link.
+Multiple
+.Ic libs
+lines can be specified.
+.It Ic buildopts Ar buildopts ...
+A list of build options to be added to every make target.
+.It Ic ln Ar progname linkname
+Causes the crunched binary to invoke
+.Ar progname
+whenever
+.Ar linkname
+appears in
+.Va argv[0] .
+This allows programs that change their behavior when
+run under different names to operate correctly.
+.El
+.Pp
+To handle specialized situations, such as when the source is not
+available or not built via a conventional
+.Pa Makefile ,
+the following
+.Ic special
+commands can be used to set
+.Nm
+parameters for a component program.
+.Bl -tag -width indent
+.It Ic special Ar progname Ic srcdir Ar pathname
+Set the source directory for
+.Ar progname .
+This is normally calculated by searching the specified
+.Ic srcdirs
+for a directory named
+.Ar progname .
+.It Ic special Ar progname Ic objdir Ar pathname
+Set the
+.Pa obj
+directory for
+.Ar progname .
+The
+.Pa obj
+directory is normally calculated by looking for a directory
+whose name is that of the source directory prepended by
+one of the following components, in order of priority:
+the
+.Fl p
+argument passed to the command line; or,
+the value of the
+.Ev MAKEOBJDIRPREFIX
+environment variable, or
+.Pa /usr/obj .
+If the directory is not found, the
+.Ic srcdir
+itself becomes the
+.Ic objdir .
+.It Ic special Ar progname Ic buildopts Ar buildopts
+Define a set of build options that should be added to
+.Xr make 1
+targets in addition to those specified using
+.Ic buildopts
+when processing
+.Ar progname .
+.It Ic special Ar progname Ic objs Ar object-file-name ...
+Set the list of object files for program
+.Ar progname .
+This is normally calculated by constructing a temporary makefile that includes
+.Dq Ic srcdir Ns / Ns Pa Makefile
+and outputs the value of
+.Va $(OBJS) .
+.It Ic special Ar progname Ic objpaths Ar full-pathname-to-object-file ...
+Sets the pathnames of the object files for program
+.Ar progname .
+This is normally calculated by prepending the
+.Ic objdir
+pathname to each file in the
+.Ic objs
+list.
+.It Ic special Ar progname Ic objvar Ar variable_name
+Sets the name of the
+.Xr make 1
+variable which holds the list of
+object files for program
+.Ar progname .
+This is normally
+.Va OBJS
+but some
+.Pa Makefile Ns s
+might like to use other conventions or
+prepend the program's name to the variable, e.g.\&
+.Va SSHD_OBJS .
+.It Ic special Ar progname Ic lib Ar library-name ...
+Specifies libraries to be linked with object files to produce
+.Ar progname Ns Pa .lo .
+This can be useful with libraries which redefine routines in
+the standard libraries, or poorly written libraries which
+reference symbols in the object files.
+.It Ic special Ar progname Ic keep Ar symbol-name ...
+Add specified list of symbols to the keep list for program
+.Ar progname .
+An underscore
+.Pq Ql _
+is prepended to each symbol and it becomes the argument to a
+.Fl k
+option for the
+.Xr crunchide 1
+phase.
+This option is to be used as a last resort as its use can cause a
+symbol conflict, however in certain instances it may be the only way to
+have a symbol resolve.
+.It Ic special Ar progname Ic ident Ar identifier
+Set the
+.Pa Makefile Ns / Ns Tn C
+identifier for
+.Ar progname .
+This is normally generated from a
+.Ar progname ,
+mapping
+.Ql -
+to
+.Ql _
+and ignoring all other non-identifier characters.
+This leads to programs named
+.Qq Li foo.bar
+and
+.Qq Li foobar
+to map to the same identifier.
+.El
+.Pp
+Only the
+.Ic objpaths
+parameter is actually needed by
+.Nm ,
+but it is calculated from
+.Ic objdir
+and
+.Ic objs ,
+which are in turn calculated from
+.Ic srcdir ,
+so is sometimes convenient to specify the earlier parameters and let
+.Nm
+calculate forward from there if it can.
+.Pp
+The makefile produced by
+.Nm
+contains an optional
+.Ic objs
+target that will build the object files for each component program by
+running
+.Xr make 1
+inside that program's source directory.
+For this to work the
+.Ic srcdir
+and
+.Ic objs
+parameters must also be valid.
+If they are not valid for a particular program, that
+program is skipped in the
+.Ic objs
+target.
+.Sh EXAMPLES
+Here is an example
+.Nm
+input conf file, named
+.Dq Pa kcopy.conf :
+.Bd -literal -offset indent
+srcdirs /usr/src/bin /usr/src/sbin
+
+progs test cp echo sh fsck halt init mount umount myinstall
+progs anotherprog
+ln test [       # test can be invoked via [
+ln sh -sh       # init invokes the shell with "-sh" in argv[0]
+
+special myprog objpaths /homes/leroy/src/myinstall.o # no sources
+
+special anotherprog -DNO_FOO WITHOUT_BAR=YES
+
+libs -lutil -lcrypt
+.Ed
+.Pp
+This conf file specifies a small crunched binary consisting of some
+basic system utilities plus a homegrown install program
+.Dq Pa myinstall ,
+for which no source directory is specified, but its object file is
+specified directly with the
+.Ic special
+line.
+.Pp
+Additionally when
+.Dq Pa anotherprog
+is built the arguments
+.Pp
+.Dl -DNO_FOO WITHOUT_BAR=YES
+.Pp
+are added to all build targets.
+.Pp
+The crunched binary
+.Dq Pa kcopy
+can be built as follows:
+.Bd -literal -offset indent
+% crunchgen -m Makefile kcopy.conf    # gen Makefile and kcopy.c
+% make objs             # build the component programs' .o files
+% make                  # build the crunched binary kcopy
+% kcopy sh              # test that this invokes a sh shell
+$                      # it works!
+.Ed
+.Pp
+At this point the binary
+.Dq Pa kcopy
+can be copied onto an install floppy
+and hard-linked to the names of the component programs.
+.Sh SEE ALSO
+.Xr crunchide 1 ,
+.Xr make 1
+.Sh CAVEATS
+While
+.Nm
+takes care to eliminate link conflicts between the component programs
+of a crunched binary, conflicts are still possible between the
+libraries that are linked in.
+Some shuffling in the order of
+libraries may be required, and in some rare cases two libraries may
+have an unresolvable conflict and thus cannot be crunched together.
+.Pp
+Some versions of the
+.Bx
+build environment do not by default build the
+intermediate object file for single-source file programs.
+The
+.Dq Li make objs
+must then be used to get those object files built, or
+some other arrangements made.
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An James da Silva Aq jds@cs.umd.edu .
+.Pp
+Copyright (c) 1994 University of Maryland.
+All Rights Reserved.
diff --git a/usr.bin/crunch/crunchgen/crunchgen.c b/usr.bin/crunch/crunchgen/crunchgen.c
new file mode 100644 (file)
index 0000000..3e20625
--- /dev/null
@@ -0,0 +1,1157 @@
+/*
+ * Copyright (c) 1994 University of Maryland
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: James da Silva, Systems Design and Analysis Group
+ *                        Computer Science Department
+ *                        University of Maryland at College Park
+ *
+ * $FreeBSD: src/usr.sbin/crunch/crunchgen/crunchgen.c,v 1.12.2.10 2002/04/14 20:55:21 luigi Exp $
+ * $DragonFly: src/usr.sbin/crunch/crunchgen/crunchgen.c,v 1.4 2005/10/30 23:00:57 swildner Exp $
+ */
+/*
+ * ========================================================================
+ * crunchgen.c
+ *
+ * Generates a Makefile and main C file for a crunched executable,
+ * from specs given in a .conf file.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define CRUNCH_VERSION "0.2"
+
+#define MAXLINELEN     16384
+#define MAXFIELDS      2048
+
+
+/* internal representation of conf file: */
+
+/* simple lists of strings suffice for most parms */
+
+typedef struct strlst {
+       struct strlst *next;
+       char *str;
+} strlst_t;
+
+/* progs have structure, each field can be set with "special" or calculated */
+
+typedef struct prog {
+       struct prog *next;      /* link field */
+       char *name;             /* program name */
+       char *ident;            /* C identifier for the program name */
+       char *srcdir;
+       char *realsrcdir;
+       char *objdir;
+       char *objvar;           /* Makefile variable to replace OBJS */
+       strlst_t *objs, *objpaths;
+       strlst_t *buildopts;
+       strlst_t *keeplist;
+       strlst_t *links;
+       strlst_t *libs;
+       int goterror;
+} prog_t;
+
+
+/* global state */
+
+strlst_t *buildopts = NULL;
+strlst_t *srcdirs   = NULL;
+strlst_t *libs      = NULL;
+prog_t   *progs     = NULL;
+
+char confname[MAXPATHLEN], infilename[MAXPATHLEN];
+char outmkname[MAXPATHLEN], outcfname[MAXPATHLEN], execfname[MAXPATHLEN];
+char tempfname[MAXPATHLEN], cachename[MAXPATHLEN], curfilename[MAXPATHLEN];
+char outhdrname[MAXPATHLEN] ;  /* user-supplied header for *.mk */
+char *objprefix;               /* where are the objects ? */
+int linenum = -1;
+int goterror = 0;
+
+int verbose, readcache;                /* options */
+int reading_cache;
+int makeobj = 0;               /* add 'make obj' rules to the makefile */
+
+int list_mode;
+
+/* general library routines */
+
+void status(char *str);
+void out_of_memory(void);
+void add_string(strlst_t **listp, char *str);
+int is_dir(char *pathname);
+int is_nonempty_file(char *pathname);
+
+/* helper routines for main() */
+
+void usage(void);
+void parse_conf_file(void);
+void gen_outputs(void);
+
+
+int
+main(int argc, char **argv)
+{
+       char *p;
+       int optc;
+
+       verbose = 1;
+       readcache = 1;
+       *outmkname = *outcfname = *execfname = '\0';
+
+       p = getenv("MAKEOBJDIRPREFIX");
+       if (p == NULL || *p == '\0')
+               objprefix = "/usr/obj"; /* default */
+       else
+               if ((objprefix = strdup(p)) == NULL)
+                       out_of_memory();
+
+       while((optc = getopt(argc, argv, "lh:m:c:e:p:foq")) != -1) {
+               switch(optc) {
+               case 'f':
+                       readcache = 0;
+                       break;
+               case 'o':
+                       makeobj = 1;
+                       break;
+               case 'q':
+                       verbose = 0;
+                       break;
+
+               case 'm':
+                       strlcpy(outmkname, optarg, sizeof(outmkname));
+                       break;
+               case 'p':
+                       if ((objprefix = strdup(optarg)) == NULL)
+                               out_of_memory();
+                       break;
+
+               case 'h':
+                       strlcpy(outhdrname, optarg, sizeof(outhdrname));
+                       break;
+               case 'c':
+                       strlcpy(outcfname, optarg, sizeof(outcfname));
+                       break;
+               case 'e':
+                       strlcpy(execfname, optarg, sizeof(execfname));
+                       break;
+
+               case 'l':
+                       list_mode++;
+                       verbose = 0;
+                       break;
+
+               case '?':
+               default:
+                       usage();
+               }
+       }
+
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 1)
+               usage();
+
+       /*
+        * generate filenames
+        */
+
+       strlcpy(infilename, argv[0], sizeof(infilename));
+
+       /* confname = `basename infilename .conf` */
+
+       if ((p=strrchr(infilename, '/')) != NULL)
+               strlcpy(confname, p + 1, sizeof(confname));
+       else
+               strlcpy(confname, infilename, sizeof(confname));
+
+       if ((p=strrchr(confname, '.')) != NULL && !strcmp(p, ".conf"))
+               *p = '\0';
+
+       if (!*outmkname)
+               snprintf(outmkname, sizeof(outmkname), "%s.mk", confname);
+       if (!*outcfname)
+               snprintf(outcfname, sizeof(outcfname), "%s.c", confname);
+       if (!*execfname)
+               snprintf(execfname, sizeof(execfname), "%s", confname);
+
+       snprintf(cachename, sizeof(cachename), "%s.cache", confname);
+       snprintf(tempfname, sizeof(tempfname), "%s/crunchgen_%sXXXXXX",
+       getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, confname);
+
+       parse_conf_file();
+       if (list_mode)
+               exit(goterror);
+
+       gen_outputs();
+
+       exit(goterror);
+}
+
+
+void
+usage(void)
+{
+       fprintf(stderr, "%s%s\n\t%s%s\n", "usage: crunchgen [-foq] ",
+           "[-h <makefile-header-name>] [-m <makefile>]",
+           "[-p <obj-prefix>] [-c <c-file-name>] [-e <exec-file>] ",
+           "<conffile>");
+       exit(1);
+}
+
+
+/*
+ * ========================================================================
+ * parse_conf_file subsystem
+ *
+ */
+
+/* helper routines for parse_conf_file */
+
+void parse_one_file(char *filename);
+void parse_line(char *line, int *fc, char **fv, int nf);
+void add_srcdirs(int argc, char **argv);
+void add_progs(int argc, char **argv);
+void add_link(int argc, char **argv);
+void add_libs(int argc, char **argv);
+void add_buildopts(int argc, char **argv);
+void add_special(int argc, char **argv);
+
+prog_t *find_prog(char *str);
+void add_prog(char *progname);
+
+
+void
+parse_conf_file(void)
+{
+       if (!is_nonempty_file(infilename))
+               errx(1, "fatal: input file \"%s\" not found", infilename);
+
+       parse_one_file(infilename);
+       if (readcache && is_nonempty_file(cachename)) {
+               reading_cache = 1;
+               parse_one_file(cachename);
+       }
+}
+
+
+void
+parse_one_file(char *filename)
+{
+       char *fieldv[MAXFIELDS];
+       int fieldc;
+       void (*f)(int c, char **v);
+       FILE *cf;
+       char line[MAXLINELEN];
+
+       snprintf(line, sizeof(line), "reading %s", filename);
+       status(line);
+       strlcpy(curfilename, filename, sizeof(curfilename));
+
+       if ((cf = fopen(curfilename, "r")) == NULL) {
+               warn("%s", curfilename);
+               goterror = 1;
+               return;
+       }
+
+       linenum = 0;
+       while (fgets(line, MAXLINELEN, cf) != NULL) {
+               linenum++;
+               parse_line(line, &fieldc, fieldv, MAXFIELDS);
+
+               if (fieldc < 1)
+                       continue;
+
+               if (!strcmp(fieldv[0], "srcdirs"))
+                       f = add_srcdirs;
+               else if(!strcmp(fieldv[0], "progs"))
+                       f = add_progs;
+               else if(!strcmp(fieldv[0], "ln"))
+                       f = add_link;
+               else if(!strcmp(fieldv[0], "libs"))
+                       f = add_libs;
+               else if(!strcmp(fieldv[0], "buildopts"))
+                       f = add_buildopts;
+               else if(!strcmp(fieldv[0], "special"))
+                       f = add_special;
+               else {
+                       warnx("%s:%d: skipping unknown command `%s'",
+                           curfilename, linenum, fieldv[0]);
+                       goterror = 1;
+                       continue;
+               }
+
+               if (fieldc < 2) {
+                       warnx("%s:%d: %s %s",
+                           curfilename, linenum, fieldv[0],
+                           "command needs at least 1 argument, skipping");
+                       goterror = 1;
+                       continue;
+               }
+
+               f(fieldc, fieldv);
+       }
+
+       if (ferror(cf)) {
+               warn("%s", curfilename);
+               goterror = 1;
+       }
+       fclose(cf);
+}
+
+
+void
+parse_line(char *line, int *fc, char **fv, int nf)
+{
+       char *p;
+
+       p = line;
+       *fc = 0;
+
+       while (1) {
+               while (isspace(*p))
+                       p++;
+
+               if (*p == '\0' || *p == '#')
+                       break;
+
+               if (*fc < nf)
+                       fv[(*fc)++] = p;
+
+               while (*p && !isspace(*p) && *p != '#')
+                       p++;
+
+               if (*p == '\0' || *p == '#')
+                       break;
+
+               *p++ = '\0';
+       }
+
+       if (*p)
+               *p = '\0';              /* needed for '#' case */
+}
+
+
+void
+add_srcdirs(int argc, char **argv)
+{
+       int i;
+
+       for (i = 1; i < argc; i++) {
+               if (is_dir(argv[i]))
+                       add_string(&srcdirs, argv[i]);
+               else {
+                       warnx("%s:%d: `%s' is not a directory, skipping it",
+                           curfilename, linenum, argv[i]);
+                       goterror = 1;
+               }
+       }
+}
+
+
+void
+add_progs(int argc, char **argv)
+{
+       int i;
+
+       for (i = 1; i < argc; i++)
+               add_prog(argv[i]);
+}
+
+
+void
+add_prog(char *progname)
+{
+       prog_t *p1, *p2;
+
+       /* add to end, but be smart about dups */
+
+       for (p1 = NULL, p2 = progs; p2 != NULL; p1 = p2, p2 = p2->next)
+               if (!strcmp(p2->name, progname))
+                       return;
+
+       p2 = malloc(sizeof(prog_t));
+       if(p2) {
+               memset(p2, 0, sizeof(prog_t));
+               p2->name = strdup(progname);
+       }
+       if (!p2 || !p2->name)
+               out_of_memory();
+
+       p2->next = NULL;
+       if (p1 == NULL)
+               progs = p2;
+       else
+               p1->next = p2;
+
+       p2->ident = NULL;
+       p2->srcdir = NULL;
+       p2->realsrcdir = NULL;
+       p2->objdir = NULL;
+       p2->links = NULL;
+       p2->libs = NULL;
+       p2->objs = NULL;
+       p2->keeplist = NULL;
+       p2->buildopts = NULL;
+       p2->goterror = 0;
+
+       if (list_mode)
+               printf("%s\n",progname);
+}
+
+
+void
+add_link(int argc, char **argv)
+{
+       int i;
+       prog_t *p = find_prog(argv[1]);
+
+       if (p == NULL) {
+               warnx("%s:%d: no prog %s previously declared, skipping link",
+                   curfilename, linenum, argv[1]);
+               goterror = 1;
+               return;
+       }
+
+       for (i = 2; i < argc; i++) {
+               if (list_mode)
+                       printf("%s\n",argv[i]);
+
+               add_string(&p->links, argv[i]);
+       }
+}
+
+
+void
+add_libs(int argc, char **argv)
+{
+       int i;
+
+       for(i = 1; i < argc; i++)
+               add_string(&libs, argv[i]);
+}
+
+
+void
+add_buildopts(int argc, char **argv)
+{
+       int i;
+
+       for (i = 1; i < argc; i++)
+               add_string(&buildopts, argv[i]);
+}
+
+
+void
+add_special(int argc, char **argv)
+{
+       int i;
+       prog_t *p = find_prog(argv[1]);
+
+       if (p == NULL) {
+               if (reading_cache)
+                       return;
+
+               warnx("%s:%d: no prog %s previously declared, skipping special",
+                   curfilename, linenum, argv[1]);
+               goterror = 1;
+               return;
+       }
+
+       if (!strcmp(argv[2], "ident")) {
+               if (argc != 4)
+                       goto argcount;
+               if ((p->ident = strdup(argv[3])) == NULL)
+                       out_of_memory();
+       } else if (!strcmp(argv[2], "srcdir")) {
+               if (argc != 4)
+                       goto argcount;
+               if ((p->srcdir = strdup(argv[3])) == NULL)
+                       out_of_memory();
+       } else if (!strcmp(argv[2], "objdir")) {
+               if(argc != 4)
+                       goto argcount;
+               if((p->objdir = strdup(argv[3])) == NULL)
+                       out_of_memory();
+       } else if (!strcmp(argv[2], "objs")) {
+               p->objs = NULL;
+               for (i = 3; i < argc; i++)
+                       add_string(&p->objs, argv[i]);
+       } else if (!strcmp(argv[2], "objpaths")) {
+               p->objpaths = NULL;
+               for (i = 3; i < argc; i++)
+                       add_string(&p->objpaths, argv[i]);
+       } else if (!strcmp(argv[2], "keep")) {
+               p->keeplist = NULL;
+               for(i = 3; i < argc; i++)
+                       add_string(&p->keeplist, argv[i]);
+       } else if (!strcmp(argv[2], "objvar")) {
+               if(argc != 4)
+                       goto argcount;
+               if ((p->objvar = strdup(argv[3])) == NULL)
+                       out_of_memory();
+       } else if (!strcmp(argv[2], "buildopts")) {
+               p->buildopts = NULL;
+               for (i = 3; i < argc; i++)
+                       add_string(&p->buildopts, argv[i]);
+       } else if (!strcmp(argv[2], "lib")) {
+               for (i = 3; i < argc; i++)
+                       add_string(&p->libs, argv[i]);
+       } else {
+               warnx("%s:%d: bad parameter name `%s', skipping line",
+                   curfilename, linenum, argv[2]);
+               goterror = 1;
+       }
+       return;
+
+ argcount:
+       warnx("%s:%d: too %s arguments, expected \"special %s %s <string>\"",
+           curfilename, linenum, argc < 4? "few" : "many", argv[1], argv[2]);
+       goterror = 1;
+}
+
+
+prog_t *
+find_prog(char *str)
+{
+       prog_t *p;
+
+       for (p = progs; p != NULL; p = p->next)
+               if (!strcmp(p->name, str))
+                       return p;
+
+       return NULL;
+}
+
+
+/*
+ * ========================================================================
+ * gen_outputs subsystem
+ *
+ */
+
+/* helper subroutines */
+
+void remove_error_progs(void);
+void fillin_program(prog_t *p);
+void gen_specials_cache(void);
+void gen_output_makefile(void);
+void gen_output_cfile(void);
+
+void fillin_program_objs(prog_t *p, char *path);
+void top_makefile_rules(FILE *outmk);
+void prog_makefile_rules(FILE *outmk, prog_t *p);
+void output_strlst(FILE *outf, strlst_t *lst);
+char *genident(char *str);
+char *dir_search(char *progname);
+
+
+void
+gen_outputs(void)
+{
+       prog_t *p;
+
+       for (p = progs; p != NULL; p = p->next)
+               fillin_program(p);
+
+       remove_error_progs();
+       gen_specials_cache();
+       gen_output_cfile();
+       gen_output_makefile();
+       status("");
+       fprintf(stderr,
+           "Run \"make -f %s\" to build crunched binary.\n", outmkname);
+}
+
+/*
+ * run the makefile for the program to find which objects are necessary
+ */
+void
+fillin_program(prog_t *p)
+{
+       char path[MAXPATHLEN];
+       char line[MAXLINELEN];
+       FILE *f;
+
+       snprintf(line, MAXLINELEN, "filling in parms for %s", p->name);
+       status(line);
+
+       if (!p->ident)
+               p->ident = genident(p->name);
+
+       /* look for the source directory if one wasn't specified by a special */
+       if (!p->srcdir) {
+               p->srcdir = dir_search(p->name);
+       }
+
+       /* Determine the actual srcdir (maybe symlinked). */
+       if (p->srcdir) {
+               snprintf(line, MAXLINELEN, "cd %s && echo -n `/bin/pwd`",
+                   p->srcdir);
+               f = popen(line,"r");
+               if (!f)
+                       errx(1, "Can't execute: %s\n", line);
+
+               path[0] = '\0';
+               fgets(path, sizeof path, f);
+               if (pclose(f))
+                       errx(1, "Can't execute: %s\n", line);
+
+               if (!*path)
+                       errx(1, "Can't perform pwd on: %s\n", p->srcdir);
+
+               p->realsrcdir = strdup(path);
+       }
+
+       /* Unless the option to make object files was specified the
+       * the objects will be built in the source directory unless
+       * an object directory already exists.
+       */
+       if (!makeobj && !p->objdir && p->srcdir) {
+               snprintf(line, sizeof line, "%s/%s", objprefix, p->realsrcdir);
+               if (is_dir(line)) {
+                       if ((p->objdir = strdup(line)) == NULL)
+                       out_of_memory();
+               } else
+                       p->objdir = p->realsrcdir;
+       }
+
+       /*
+       * XXX look for a Makefile.{name} in local directory first.
+       * This lets us override the original Makefile.
+       */
+       snprintf(path, sizeof(path), "Makefile.%s", p->name);
+       if (is_nonempty_file(path)) {
+               snprintf(line, MAXLINELEN, "Using %s for %s", path, p->name);
+               status(line);
+       } else
+               if (p->srcdir)
+                       snprintf(path, sizeof(path), "%s/Makefile", p->srcdir);
+       if (!p->objs && p->srcdir && is_nonempty_file(path))
+               fillin_program_objs(p, path);
+
+       if (!p->srcdir && !p->objdir && verbose)
+               warnx("%s: %s: %s",
+                   "warning: could not find source directory",
+                   infilename, p->name);
+       if (!p->objs && verbose)
+               warnx("%s: %s: warning: could not find any .o files",
+                   infilename, p->name);
+
+       if ((!p->srcdir || !p->objdir) && !p->objs)
+               p->goterror = 1;
+}
+
+void
+fillin_program_objs(prog_t *p, char *path)
+{
+       char *obj, *cp;
+       int fd, rc;
+       FILE *f;
+       char *objvar="OBJS";
+       strlst_t *s;
+       char line[MAXLINELEN];
+
+       /* discover the objs from the srcdir Makefile */
+
+       if ((fd = mkstemp(tempfname)) == -1) {
+               perror(tempfname);
+               exit(1);
+       }
+       if ((f = fdopen(fd, "w")) == NULL) {
+               warn("%s", tempfname);
+               goterror = 1;
+               return;
+       }
+       if (p->objvar)
+               objvar = p->objvar;
+
+       /*
+       * XXX include outhdrname (e.g. to contain Make variables)
+       */
+       if (outhdrname[0] != '\0')
+               fprintf(f, ".include \"%s\"\n", outhdrname);
+       fprintf(f, ".include \"%s\"\n", path);
+       if (buildopts) {
+               fprintf(f, "BUILDOPTS+=");
+               output_strlst(f, buildopts);
+       }
+       fprintf(f, ".if defined(PROG) && !defined(%s)\n", objvar);
+       fprintf(f, "%s=${PROG}.o\n", objvar);
+       fprintf(f, ".endif\n");
+       fprintf(f, "loop:\n\t@echo 'OBJS= '${%s}\n", objvar);
+
+       fprintf(f, "crunchgen_objs:\n\t@make -f %s $(BUILDOPTS) $(%s_OPTS)",
+           tempfname, p->ident);
+       for (s = p->buildopts; s != NULL; s = s->next)
+               fprintf(f, " %s", s->str);
+       fprintf(f, " loop\n");
+
+       fclose(f);
+
+       snprintf(line, MAXLINELEN, "make -f %s crunchgen_objs 2>&1", tempfname);
+       if ((f = popen(line, "r")) == NULL) {
+               warn("submake pipe");
+               goterror = 1;
+               return;
+       }
+
+       while(fgets(line, MAXLINELEN, f)) {
+               if (strncmp(line, "OBJS= ", 6)) {
+                       warnx("make error: %s", line);
+                       goterror = 1;
+                       continue;
+               }
+
+               cp = line + 6;
+               while (isspace(*cp))
+                       cp++;
+
+               while(*cp) {
+                       obj = cp;
+                       while (*cp && !isspace(*cp))
+                               cp++;
+                       if (*cp)
+                               *cp++ = '\0';
+                       add_string(&p->objs, obj);
+                       while (isspace(*cp))
+                               cp++;
+               }
+       }
+
+       if ((rc=pclose(f)) != 0) {
+               warnx("make error: make returned %d", rc);
+               goterror = 1;
+       }
+
+       unlink(tempfname);
+}
+
+void
+remove_error_progs(void)
+{
+       prog_t *p1, *p2;
+
+       p1 = NULL; p2 = progs;
+       while (p2 != NULL) {
+               if (!p2->goterror)
+                       p1 = p2, p2 = p2->next;
+               else {
+                       /* delete it from linked list */
+                       warnx("%s: %s: ignoring program because of errors",
+                           infilename, p2->name);
+                       if (p1)
+                               p1->next = p2->next;
+                       else
+                               progs = p2->next;
+                       p2 = p2->next;
+               }
+       }
+}
+
+void
+gen_specials_cache(void)
+{
+       FILE *cachef;
+       prog_t *p;
+       char line[MAXLINELEN];
+
+       snprintf(line, MAXLINELEN, "generating %s", cachename);
+       status(line);
+
+       if ((cachef = fopen(cachename, "w")) == NULL) {
+               warn("%s", cachename);
+               goterror = 1;
+               return;
+       }
+
+       fprintf(cachef, "# %s - parm cache generated from %s by crunchgen "
+           " %s\n\n",
+           cachename, infilename, CRUNCH_VERSION);
+
+       for (p = progs; p != NULL; p = p->next) {
+               fprintf(cachef, "\n");
+               if (p->srcdir)
+                       fprintf(cachef, "special %s srcdir %s\n",
+                           p->name, p->srcdir);
+               if (p->objdir)
+                       fprintf(cachef, "special %s objdir %s\n",
+                           p->name, p->objdir);
+               if (p->objs) {
+                       fprintf(cachef, "special %s objs", p->name);
+                       output_strlst(cachef, p->objs);
+               }
+               if (p->objpaths) {
+                       fprintf(cachef, "special %s objpaths", p->name);
+                       output_strlst(cachef, p->objpaths);
+               }
+       }
+       fclose(cachef);
+}
+
+
+void
+gen_output_makefile(void)
+{
+       prog_t *p;
+       FILE *outmk;
+       char line[MAXLINELEN];
+
+       snprintf(line, MAXLINELEN, "generating %s", outmkname);
+       status(line);
+
+       if ((outmk = fopen(outmkname, "w")) == NULL) {
+               warn("%s", outmkname);
+               goterror = 1;
+               return;
+       }
+
+       fprintf(outmk, "# %s - generated from %s by crunchgen %s\n\n",
+           outmkname, infilename, CRUNCH_VERSION);
+
+       if (outhdrname[0] != '\0')
+               fprintf(outmk, ".include \"%s\"\n", outhdrname);
+
+       top_makefile_rules(outmk);
+       for (p = progs; p != NULL; p = p->next)
+               prog_makefile_rules(outmk, p);
+
+       fprintf(outmk, "\n# ========\n");
+       fclose(outmk);
+}
+
+
+void
+gen_output_cfile(void)
+{
+       extern char *crunched_skel[];
+       char **cp;
+       FILE *outcf;
+       prog_t *p;
+       strlst_t *s;
+       char line[MAXLINELEN];
+
+       snprintf(line, MAXLINELEN, "generating %s", outcfname);
+       status(line);
+
+       if((outcf = fopen(outcfname, "w")) == NULL) {
+               warn("%s", outcfname);
+               goterror = 1;
+               return;
+       }
+
+       fprintf(outcf,
+           "/* %s - generated from %s by crunchgen %s */\n",
+           outcfname, infilename, CRUNCH_VERSION);
+
+       fprintf(outcf, "#define EXECNAME \"%s\"\n", execfname);
+       for (cp = crunched_skel; *cp != NULL; cp++)
+               fprintf(outcf, "%s\n", *cp);
+
+       for (p = progs; p != NULL; p = p->next)
+               fprintf(outcf, "extern int _crunched_%s_stub();\n", p->ident);
+
+       fprintf(outcf, "\nstruct stub entry_points[] = {\n");
+       for (p = progs; p != NULL; p = p->next) {
+               fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
+                   p->name, p->ident);
+               for (s = p->links; s != NULL; s = s->next)
+                       fprintf(outcf, "\t{ \"%s\", _crunched_%s_stub },\n",
+                           s->str, p->ident);
+       }
+
+       fprintf(outcf, "\t{ EXECNAME, crunched_main },\n");
+       fprintf(outcf, "\t{ NULL, NULL }\n};\n");
+       fclose(outcf);
+}
+
+
+char *
+genident(char *str)
+{
+       char *n, *s, *d;
+
+       /*
+        * generates a Makefile/C identifier from a program name,
+        * mapping '-' to '_' and ignoring all other non-identifier
+        * characters.  This leads to programs named "foo.bar" and
+        * "foobar" to map to the same identifier.
+        */
+
+       if ((n = strdup(str)) == NULL)
+               return NULL;
+       for (d = s = n; *s != '\0'; s++) {
+               if (*s == '-')
+                       *d++ = '_';
+               else if (*s == '_' || isalnum(*s))
+                       *d++ = *s;
+       }
+       *d = '\0';
+       return n;
+}
+
+
+char *
+dir_search(char *progname)
+{
+       char path[MAXPATHLEN];
+       strlst_t *dir;
+       char *srcdir;
+
+       for (dir = srcdirs; dir != NULL; dir = dir->next) {
+               snprintf(path, MAXPATHLEN, "%s/%s", dir->str, progname);
+               if (!is_dir(path))
+                       continue;
+
+               if ((srcdir = strdup(path)) == NULL)
+                       out_of_memory();
+
+               return srcdir;
+       }
+       return NULL;
+}
+
+
+void
+top_makefile_rules(FILE *outmk)
+{
+       prog_t *p;
+
+       fprintf(outmk, "LIBS+=");
+       output_strlst(outmk, libs);
+
+       if (makeobj) {
+               fprintf(outmk, "MAKEOBJDIRPREFIX?=%s\n", objprefix);
+               fprintf(outmk, "MAKE=env MAKEOBJDIRPREFIX=$(MAKEOBJDIRPREFIX) "
+                   "make\n");
+       } else {
+               fprintf(outmk, "MAKE=make\n");
+       }
+
+       if (buildopts) {
+               fprintf(outmk, "BUILDOPTS+=");
+               output_strlst(outmk, buildopts);
+       }
+
+       fprintf(outmk, "CRUNCHED_OBJS=");
+       for (p = progs; p != NULL; p = p->next)
+               fprintf(outmk, " %s.lo", p->name);
+       fprintf(outmk, "\n");
+
+       fprintf(outmk, "SUBMAKE_TARGETS=");
+       for (p = progs; p != NULL; p = p->next)
+               fprintf(outmk, " %s_make", p->ident);
+       fprintf(outmk, "\nSUBCLEAN_TARGETS=");
+       for (p = progs; p != NULL; p = p->next)
+               fprintf(outmk, " %s_clean", p->ident);
+       fprintf(outmk, "\n\n");
+
+       fprintf(outmk, "all: objs exe\nobjs: $(SUBMAKE_TARGETS)\n");
+       fprintf(outmk, "exe: %s\n", execfname);
+       fprintf(outmk, "%s: %s.o $(CRUNCHED_OBJS)\n", execfname, execfname);
+       fprintf(outmk, "\t$(CC) -static -o %s %s.o $(CRUNCHED_OBJS) $(LIBS)\n",
+           execfname, execfname);
+       fprintf(outmk, "\tstrip %s\n", execfname);
+       fprintf(outmk, "realclean: clean subclean\n");
+       fprintf(outmk, "clean:\n\trm -f %s *.lo *.o *_stub.c\n", execfname);
+       fprintf(outmk, "subclean: $(SUBCLEAN_TARGETS)\n");
+}
+
+
+void
+prog_makefile_rules(FILE *outmk, prog_t *p)
+{
+       strlst_t *lst;
+
+       fprintf(outmk, "\n# -------- %s\n\n", p->name);
+
+       fprintf(outmk, "%s_OBJDIR=", p->ident);
+       if (p->objdir)
+               fprintf(outmk, "%s", p->objdir);
+       else
+               fprintf(outmk, "$(MAKEOBJDIRPREFIX)/$(%s_REALSRCDIR)\n",
+                   p->ident);
+       fprintf(outmk, "\n");
+
+       if (p->srcdir && p->objs) {
+               fprintf(outmk, "%s_SRCDIR=%s\n", p->ident, p->srcdir);
+               fprintf(outmk, "%s_REALSRCDIR=%s\n", p->ident, p->realsrcdir);
+
+               fprintf(outmk, "%s_OBJS=", p->ident);
+               output_strlst(outmk, p->objs);
+               if (p->buildopts != NULL) {
+                       fprintf(outmk, "%s_OPTS+=", p->ident);
+                       output_strlst(outmk, p->buildopts);
+               }
+               fprintf(outmk, "%s_make:\n", p->ident);
+               fprintf(outmk, "\t(cd $(%s_SRCDIR) && ", p->ident);
+               if (makeobj)
+                       fprintf(outmk, "$(MAKE) obj && ");
+               fprintf(outmk, "\\\n");
+               fprintf(outmk, "\t\t$(MAKE) $(BUILDOPTS) $(%s_OPTS) depend &&",
+                   p->ident);
+               fprintf(outmk, "\\\n");
+               fprintf(outmk, "\t\t$(MAKE) $(BUILDOPTS) $(%s_OPTS) "
+                   "$(%s_OBJS))",
+                   p->ident, p->ident);
+               fprintf(outmk, "\n");
+               fprintf(outmk, "%s_clean:\n", p->ident);
+               fprintf(outmk, "\t(cd $(%s_SRCDIR) && $(MAKE) $(BUILDOPTS) clean cleandepend)\n\n",
+                   p->ident);
+       } else {
+               fprintf(outmk, "%s_make:\n", p->ident);
+               fprintf(outmk, "\t@echo \"** cannot make objs for %s\"\n\n",
+                   p->name);
+       }
+
+       fprintf(outmk, "%s_OBJPATHS=", p->ident);
+       if (p->objpaths)
+               output_strlst(outmk, p->objpaths);
+       else {
+               for (lst = p->objs; lst != NULL; lst = lst->next) {
+                       fprintf(outmk, " $(%s_OBJDIR)/%s", p->ident, lst->str);
+               }
+               fprintf(outmk, "\n");
+       }
+       if (p->libs) {
+               fprintf(outmk, "%s_LIBS=", p->ident);
+               output_strlst(outmk, p->libs);
+       }
+
+       fprintf(outmk, "%s_stub.c:\n", p->name);
+       fprintf(outmk, "\techo \""
+           "int _crunched_%s_stub(int argc, char **argv, char **envp)"
+           "{return main(argc,argv,envp);}\" >%s_stub.c\n",
+           p->ident, p->name);
+       fprintf(outmk, "%s.lo: %s_stub.o $(%s_OBJPATHS)",
+           p->name, p->name, p->ident);
+       if (p->libs)
+               fprintf(outmk, " $(%s_LIBS)", p->ident);
+       fprintf(outmk, "\n");
+       fprintf(outmk, "\tld -dc -r -o %s.lo %s_stub.o $(%s_OBJPATHS)",
+           p->name, p->name, p->ident);
+       if (p->libs)
+               fprintf(outmk, " $(%s_LIBS)", p->ident);
+       fprintf(outmk, "\n");
+       fprintf(outmk, "\tcrunchide -k _crunched_%s_stub ", p->ident);
+       for (lst = p->keeplist; lst != NULL; lst = lst->next)
+               fprintf(outmk, "-k _%s ", lst->str);
+       fprintf(outmk, "%s.lo\n", p->name);
+}
+
+void
+output_strlst(FILE *outf, strlst_t *lst)
+{
+       for (; lst != NULL; lst = lst->next)
+               fprintf(outf, " %s", lst->str);
+       fprintf(outf, "\n");
+}
+
+
+/*
+ * ========================================================================
+ * general library routines
+ *
+ */
+
+void
+status(char *str)
+{
+       static int lastlen = 0;
+       int len, spaces;
+
+       if (!verbose)
+               return;
+
+       len = strlen(str);
+       spaces = lastlen - len;
+       if (spaces < 1)
+               spaces = 1;
+
+       fprintf(stderr, " [%s]%*.*s\r", str, spaces, spaces, " ");
+       fflush(stderr);
+       lastlen = len;
+}
+
+
+void
+out_of_memory(void)
+{
+       err(1, "%s: %d: out of memory, stopping", infilename, linenum);
+}
+
+
+void
+add_string(strlst_t **listp, char *str)
+{
+       strlst_t *p1, *p2;
+
+       /* add to end, but be smart about dups */
+
+       for (p1 = NULL, p2 = *listp; p2 != NULL; p1 = p2, p2 = p2->next)
+               if (!strcmp(p2->str, str))
+                       return;
+
+       p2 = malloc(sizeof(strlst_t));
+       if (p2) {
+               p2->next = NULL;
+               p2->str = strdup(str);
+       }
+       if (!p2 || !p2->str)
+               out_of_memory();
+
+       if (p1 == NULL)
+               *listp = p2;
+       else
+               p1->next = p2;
+}
+
+
+int
+is_dir(char *pathname)
+{
+       struct stat buf;
+
+       if (stat(pathname, &buf) == -1)
+               return 0;
+
+       return S_ISDIR(buf.st_mode);
+}
+
+int
+is_nonempty_file(char *pathname)
+{
+       struct stat buf;
+
+       if (stat(pathname, &buf) == -1)
+               return 0;
+
+       return S_ISREG(buf.st_mode) && buf.st_size > 0;
+}
diff --git a/usr.bin/crunch/crunchgen/mkskel.sh b/usr.bin/crunch/crunchgen/mkskel.sh
new file mode 100644 (file)
index 0000000..fd53d78
--- /dev/null
@@ -0,0 +1,15 @@
+#! /bin/sh
+# idea and sed lines taken straight from flex
+
+cat <<!EOF
+/* File created via mkskel.sh */
+
+char *crunched_skel[] = {
+!EOF
+
+sed 's/\\/&&/g' $* | sed 's/"/\\"/g' | sed 's/.*/  "&",/'
+
+cat <<!EOF
+  0
+};
+!EOF
diff --git a/usr.bin/crunch/crunchide/Makefile b/usr.bin/crunch/crunchide/Makefile
new file mode 100644 (file)
index 0000000..eb022f0
--- /dev/null
@@ -0,0 +1,13 @@
+# $FreeBSD: src/usr.sbin/crunch/crunchide/Makefile,v 1.2.6.1 2002/07/25 09:33:17 ru Exp $
+# $DragonFly: src/usr.sbin/crunch/crunchide/Makefile,v 1.2 2003/06/17 04:29:53 dillon Exp $
+
+PROG=   crunchide
+SRCS=  crunchide.c exec_elf32.c exec_elf64.c
+
+TARGET_ARCH?=  ${MACHINE_ARCH}
+.if ${TARGET_ARCH} == i386 && ${MACHINE_ARCH} == i386
+SRCS+= exec_aout.c
+.endif
+CFLAGS+=-Darch_${TARGET_ARCH}
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/crunch/crunchide/crunchide.1 b/usr.bin/crunch/crunchide/crunchide.1
new file mode 100644 (file)
index 0000000..1327cc9
--- /dev/null
@@ -0,0 +1,87 @@
+.\"
+.\" Copyright (c) 1994 University of Maryland
+.\" All Rights Reserved.
+.\"
+.\" Permission to use, copy, modify, distribute, and sell this software and its
+.\" documentation for any purpose is hereby granted without fee, 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 U.M. not be used in advertising or
+.\" publicity pertaining to distribution of the software without specific,
+.\" written prior permission.  U.M. makes no representations about the
+.\" suitability of this software for any purpose.  It is provided "as is"
+.\" without express or implied warranty.
+.\"
+.\" U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+.\" BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+.\" IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Author: James da Silva, Systems Design and Analysis Group
+.\"                       Computer Science Department
+.\"                       University of Maryland at College Park
+.\" $FreeBSD: src/usr.sbin/crunch/crunchide/crunchide.1,v 1.5.2.5 2003/03/12 22:08:14 trhodes Exp $
+.\" $DragonFly: src/usr.sbin/crunch/crunchide/crunchide.1,v 1.2 2003/06/17 04:29:53 dillon Exp $
+.\"
+.Dd June 14, 1994
+.Dt CRUNCHIDE 1
+.Os
+.Sh NAME
+.Nm crunchide
+.Nd hides symbol names from ld, for crunching programs together
+.Sh SYNOPSIS
+.Nm
+.Op Fl f Ar keep-list-file
+.Op Fl k Ar keep-symbol
+.Op Ar object-file ...
+.Sh DESCRIPTION
+The
+.Nm
+utility hides the global symbols of
+.Ar object-file
+such that they are ignored by subsequent runs of the linker,
+.Xr ld 1 .
+Some symbols may be left visible via the
+.Fl k Ar keep-symbol
+and
+.Fl f Ar keep-list-file
+options.  The
+.Ar keep-list-file
+must contain a list of symbols to keep visible, one symbol per line.
+The names given by
+.Ar keep-symbol
+or in
+.Ar keep-list-file
+should be C names.  For example,
+to keep the C function
+.Dq foo
+visible, the option
+.Dq -k foo
+should be used.
+.Pp
+The
+.Nm
+utility is designed as a companion program for
+.Xr crunchgen 1 ,
+which automates the process of creating crunched binaries from
+multiple component programs.
+.Sh SEE ALSO
+.Xr crunchgen 1 ,
+.Xr ld 1
+.Sh AUTHORS
+The
+.Nm crunch
+utility was written by
+.An James da Silva Aq jds@cs.umd.edu .
+.Pp
+Copyright (c) 1994 University of Maryland.  All Rights Reserved.
+.Pp
+.An Chris Demetriou Aq cgd@netbsd.org
+reorganized
+.Nm
+so that it supported multiple object formats, and added
+ELF object support and ECOFF object recognition.
+.Pp
+Copyright (c) 1997 Christopher G. Demetriou.  All Rights Reserved.
diff --git a/usr.bin/crunch/crunchide/crunchide.c b/usr.bin/crunch/crunchide/crunchide.c
new file mode 100644 (file)
index 0000000..d9a0902
--- /dev/null
@@ -0,0 +1,274 @@
+/*     $NetBSD: crunchide.c,v 1.8 1997/11/01 06:51:45 lukem Exp $      */
+/* $FreeBSD: src/usr.sbin/crunch/crunchide/crunchide.c,v 1.6.6.1 2002/07/25 09:33:17 ru Exp $ */
+/* $DragonFly: src/usr.sbin/crunch/crunchide/crunchide.c,v 1.4 2003/11/16 14:10:45 eirikn Exp $ */
+/*
+ * Copyright (c) 1997 Christopher G. Demetriou.  All rights reserved.
+ * Copyright (c) 1994 University of Maryland
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: James da Silva, Systems Design and Analysis Group
+ *                        Computer Science Department
+ *                        University of Maryland at College Park
+ *
+ * $NetBSD: crunchide.c,v 1.8 1997/11/01 06:51:45 lukem Exp $
+ */
+/*
+ * crunchide.c - tiptoes through an a.out symbol table, hiding all defined
+ *     global symbols.  Allows the user to supply a "keep list" of symbols
+ *     that are not to be hidden.  This program relies on the use of the
+ *     linker's -dc flag to actually put global bss data into the file's
+ *     bss segment (rather than leaving it as undefined "common" data).
+ *
+ *     The point of all this is to allow multiple programs to be linked
+ *     together without getting multiple-defined errors.
+ *
+ *     For example, consider a program "foo.c".  It can be linked with a
+ *     small stub routine, called "foostub.c", eg:
+ *         int foo_main(int argc, char **argv){ return main(argc, argv); }
+ *      like so:
+ *         cc -c foo.c foostub.c
+ *         ld -dc -r foo.o foostub.o -o foo.combined.o
+ *         crunchide -k _foo_main foo.combined.o
+ *     at this point, foo.combined.o can be linked with another program
+ *     and invoked with "foo_main(argc, argv)".  foo's main() and any
+ *     other globals are hidden and will not conflict with other symbols.
+ *
+ * TODO:
+ *     - resolve the theoretical hanging reloc problem (see check_reloc()
+ *       below). I have yet to see this problem actually occur in any real
+ *       program. In what cases will gcc/gas generate code that needs a
+ *       relative reloc from a global symbol, other than PIC?  The
+ *       solution is to not hide the symbol from the linker in this case,
+ *       but to generate some random name for it so that it doesn't link
+ *       with anything but holds the place for the reloc.
+ *      - arrange that all the BSS segments start at the same address, so
+ *       that the final crunched binary BSS size is the max of all the
+ *       component programs' BSS sizes, rather than their sum.
+ */
+#include <sys/cdefs.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <a.out.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+
+#include "extern.h"
+
+char *pname = "crunchide";
+
+void usage(void);
+
+void add_to_keep_list(char *symbol);
+void add_file_to_keep_list(char *filename);
+
+int hide_syms(const char *filename);
+
+int verbose;
+
+int main(int, char *[]);
+
+int
+main(int argc, char **argv)
+{
+    int ch, errors;
+
+    if(argc > 0) pname = argv[0];
+
+    while ((ch = getopt(argc, argv, "k:f:v")) != -1)
+       switch(ch) {
+       case 'k':
+           add_to_keep_list(optarg);
+           break;
+       case 'f':
+           add_file_to_keep_list(optarg);
+           break;
+       case 'v':
+           verbose = 1;
+           break;
+       default:
+           usage();
+       }
+
+    argc -= optind;
+    argv += optind;
+
+    if(argc == 0) usage();
+
+    errors = 0;
+    while(argc) {
+       if (hide_syms(*argv))
+               errors = 1;
+       argc--, argv++;
+    }
+
+    return errors;
+}
+
+void
+usage(void)
+{
+    fprintf(stderr,
+           "usage: %s [-k <symbol-name>] [-f <keep-list-file>] <files> ...\n",
+           pname);
+    exit(1);
+}
+
+/* ---------------------------- */
+
+struct keep {
+    struct keep *next;
+    char *sym;
+} *keep_list;
+
+void
+add_to_keep_list(char *symbol)
+{
+    struct keep *newp, *prevp, *curp;
+    int cmp;
+
+    cmp = 0;
+
+    for(curp = keep_list, prevp = NULL; curp; prevp = curp, curp = curp->next)
+       if((cmp = strcmp(symbol, curp->sym)) <= 0) break;
+
+    if(curp && cmp == 0)
+       return; /* already in table */
+
+    newp = (struct keep *) malloc(sizeof(struct keep));
+    if(newp) newp->sym = strdup(symbol);
+    if(newp == NULL || newp->sym == NULL) {
+       fprintf(stderr, "%s: out of memory for keep list\n", pname);
+       exit(1);
+    }
+
+    newp->next = curp;
+    if(prevp) prevp->next = newp;
+    else keep_list = newp;
+}
+
+int
+in_keep_list(const char *symbol)
+{
+    struct keep *curp;
+    int cmp;
+
+    cmp = 0;
+
+    for(curp = keep_list; curp; curp = curp->next)
+       if((cmp = strcmp(symbol, curp->sym)) <= 0) break;
+
+    return curp && cmp == 0;
+}
+
+void
+add_file_to_keep_list(char *filename)
+{
+    FILE *keepf;
+    char symbol[1024];
+    int len;
+
+    if((keepf = fopen(filename, "r")) == NULL) {
+       perror(filename);
+       usage();
+    }
+
+    while(fgets(symbol, 1024, keepf)) {
+       len = strlen(symbol);
+       if(len && symbol[len-1] == '\n')
+           symbol[len-1] = '\0';
+
+       add_to_keep_list(symbol);
+    }
+    fclose(keepf);
+}
+
+/* ---------------------------- */
+
+struct {
+       const char *name;
+       int     (*check)(int, const char *);    /* 1 if match, zero if not */
+       int     (*hide)(int, const char *);     /* non-zero if error */
+} exec_formats[] = {
+#if defined(__i386__) && defined(arch_i386)
+#ifdef NLIST_AOUT
+       {       "a.out",        check_aout,     hide_aout,      },
+#endif
+#endif
+#ifdef NLIST_ECOFF
+       {       "ECOFF",        check_elf64,    hide_elf64,     },
+#endif
+#ifdef NLIST_ELF32
+       {       "ELF32",        check_elf32,    hide_elf32,     },
+#endif
+#ifdef NLIST_ELF64
+       {       "ELF64",        check_elf64,    hide_elf64,     },
+#endif
+};
+
+int
+hide_syms(const char *filename)
+{
+       int fd, i, n, rv;
+
+       fd = open(filename, O_RDWR, 0);
+       if (fd == -1) {
+               perror(filename);
+               return 1;
+       }
+
+       rv = 0;
+
+        n = sizeof exec_formats / sizeof exec_formats[0];
+        for (i = 0; i < n; i++) {
+               if (lseek(fd, 0, SEEK_SET) != 0) {
+                       perror(filename);
+                       goto err;
+               }
+                if ((*exec_formats[i].check)(fd, filename) != 0)
+                        break;
+       }
+       if (i == n) {
+               fprintf(stderr, "%s: unknown executable format\n", filename);
+               goto err;
+       }
+
+       if (verbose)
+               fprintf(stderr, "%s is an %s binary\n", filename,
+                   exec_formats[i].name);
+
+       if (lseek(fd, 0, SEEK_SET) != 0) {
+               perror(filename);
+               goto err;
+       }
+       rv = (*exec_formats[i].hide)(fd, filename);
+
+out:
+       close (fd);
+       return (rv);
+
+err:
+       rv = 1;
+       goto out;
+}
diff --git a/usr.bin/crunch/crunchide/exec_aout.c b/usr.bin/crunch/crunchide/exec_aout.c
new file mode 100644 (file)
index 0000000..ab49da9
--- /dev/null
@@ -0,0 +1,207 @@
+/*     $NetBSD: exec_aout.c,v 1.6 1997/08/02 21:30:17 perry Exp $      */
+/*
+ * Copyright (c) 1997 Christopher G. Demetriou.  All rights reserved.
+ * Copyright (c) 1994 University of Maryland
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 U.M. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  U.M. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: James da Silva, Systems Design and Analysis Group
+ *                        Computer Science Department
+ *                        University of Maryland at College Park
+ *
+ * $NetBSD: exec_aout.c,v 1.6 1997/08/02 21:30:17 perry Exp $
+ * $FreeBSD: src/usr.sbin/crunch/crunchide/exec_aout.c,v 1.1.6.1 2002/07/25 09:33:17 ru Exp $
+ * $DragonFly: src/usr.sbin/crunch/crunchide/exec_aout.c,v 1.5 2004/02/08 10:48:30 rob Exp $
+ */
+#include <sys/cdefs.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <a.out.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+
+#include "extern.h"
+
+#if defined(NLIST_AOUT)
+
+int nsyms, ntextrel, ndatarel;
+struct exec *hdrp;
+char *aoutdata, *strbase;
+struct relocation_info *textrel, *datarel;
+struct nlist *symbase;
+
+
+#define SYMSTR(sp)     (&strbase[(sp)->n_un.n_strx])
+
+/* is the symbol a global symbol defined in the current file? */
+#define IS_GLOBAL_DEFINED(sp) \
+                  (((sp)->n_type & N_EXT) && ((sp)->n_type & N_TYPE) != N_UNDF)
+
+#ifdef arch_sparc
+/* is the relocation entry dependent on a symbol? */
+#define IS_SYMBOL_RELOC(rp)   \
+       ((rp)->r_extern || \
+       ((rp)->r_type >= RELOC_BASE10 && (rp)->r_type <= RELOC_BASE22) || \
+       (rp)->r_type == RELOC_JMP_TBL)
+#else
+/* is the relocation entry dependent on a symbol? */
+#define IS_SYMBOL_RELOC(rp)   \
+                  ((rp)->r_extern||(rp)->r_baserel||(rp)->r_jmptable)
+#endif
+
+static void check_reloc(const char *filename, struct relocation_info *relp);
+
+int
+check_aout(int inf, const char *filename)
+{
+    struct stat infstat;
+    struct exec eh;
+
+    /*
+     * check the header to make sure it's an a.out-format file.
+     */
+
+    if(fstat(inf, &infstat) == -1)
+       return 0;
+    if(infstat.st_size < sizeof eh)
+       return 0;
+    if(read(inf, &eh, sizeof eh) != sizeof eh)
+       return 0;
+
+    if(N_BADMAG(eh))
+       return 0;
+
+    return 1;
+}
+
+int
+hide_aout(int inf, const char *filename)
+{
+    struct stat infstat;
+    struct relocation_info *relp;
+    struct nlist *symp;
+    int rc;
+
+    /*
+     * do some error checking.
+     */
+
+    if(fstat(inf, &infstat) == -1) {
+       perror(filename);
+       return 1;
+    }
+
+    /*
+     * Read the entire file into memory.  XXX - Really, we only need to
+     * read the header and from TRELOFF to the end of the file.
+     */
+
+    if((aoutdata = (char *) malloc(infstat.st_size)) == NULL) {
+       fprintf(stderr, "%s: too big to read into memory\n", filename);
+       return 1;
+    }
+
+    if((rc = read(inf, aoutdata, infstat.st_size)) < infstat.st_size) {
+       fprintf(stderr, "%s: read error: %s\n", filename,
+               rc == -1? strerror(errno) : "short read");
+       return 1;
+    }
+
+    /*
+     * Calculate offsets and sizes from the header.
+     */
+
+    hdrp = (struct exec *) aoutdata;
+
+#if defined  (__DragonFly__) || defined (__FreeBSD__)
+    textrel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp));
+    datarel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp) +
+                                         hdrp->a_trsize);
+#else
+    textrel = (struct relocation_info *) (aoutdata + N_TRELOFF(*hdrp));
+    datarel = (struct relocation_info *) (aoutdata + N_DRELOFF(*hdrp));
+#endif
+    symbase = (struct nlist *)          (aoutdata + N_SYMOFF(*hdrp));
+    strbase = (char *)                          (aoutdata + N_STROFF(*hdrp));
+
+    ntextrel = hdrp->a_trsize / sizeof(struct relocation_info);
+    ndatarel = hdrp->a_drsize / sizeof(struct relocation_info);
+    nsyms    = hdrp->a_syms   / sizeof(struct nlist);
+
+    /*
+     * Zap the type field of all globally-defined symbols.  The linker will
+     * subsequently ignore these entries.  Don't zap any symbols in the
+     * keep list.
+     */
+
+    for(symp = symbase; symp < symbase + nsyms; symp++) {
+       if(!IS_GLOBAL_DEFINED(symp))            /* keep undefined syms */
+           continue;
+
+       /* keep (C) symbols which are on the keep list */
+       if(SYMSTR(symp)[0] == '_' && in_keep_list(SYMSTR(symp) + 1))
+           continue;
+
+       symp->n_type = 0;
+    }
+
+    /*
+     * Check whether the relocation entries reference any symbols that we
+     * just zapped.  I don't know whether ld can handle this case, but I
+     * haven't encountered it yet.  These checks are here so that the program
+     * doesn't fail silently should such symbols be encountered.
+     */
+
+    for(relp = textrel; relp < textrel + ntextrel; relp++)
+       check_reloc(filename, relp);
+    for(relp = datarel; relp < datarel + ndatarel; relp++)
+       check_reloc(filename, relp);
+
+    /*
+     * Write the .o file back out to disk.  XXX - Really, we only need to
+     * write the symbol table entries back out.
+     */
+    lseek(inf, 0, SEEK_SET);
+    if((rc = write(inf, aoutdata, infstat.st_size)) < infstat.st_size) {
+       fprintf(stderr, "%s: write error: %s\n", filename,
+               rc == -1? strerror(errno) : "short write");
+       return 1;
+    }
+
+    return 0;
+}
+
+
+static void
+check_reloc(const char *filename, struct relocation_info *relp)
+{
+    /* bail out if we zapped a symbol that is needed */
+    if(IS_SYMBOL_RELOC(relp) && symbase[relp->r_symbolnum].n_type == 0) {
+       fprintf(stderr,
+               "%s: oops, have hanging relocation for %s: bailing out!\n",
+               filename, SYMSTR(&symbase[relp->r_symbolnum]));
+       exit(1);
+    }
+}
+
+#endif /* defined(NLIST_AOUT) */
diff --git a/usr.bin/crunch/crunchide/exec_elf32.c b/usr.bin/crunch/crunchide/exec_elf32.c
new file mode 100644 (file)
index 0000000..b0c3782
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 1997 Christopher G. Demetriou.  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 Christopher G. Demetriou
+ *     for the NetBSD Project.
+ * 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.
+ *
+ * $NetBSD: exec_elf32.c,v 1.4 1997/08/12 06:07:24 mikel Exp $
+ * $FreeBSD: src/usr.sbin/crunch/crunchide/exec_elf32.c,v 1.1.6.2 2002/07/25 09:33:17 ru Exp $
+ * $DragonFly: src/usr.sbin/crunch/crunchide/exec_elf32.c,v 1.2 2003/06/17 04:29:53 dillon Exp $
+ */
+
+#include <sys/cdefs.h>
+
+#ifndef ELFSIZE
+#define ELFSIZE         32
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+#if (defined(NLIST_ELF32) && (ELFSIZE == 32)) || \
+    (defined(NLIST_ELF64) && (ELFSIZE == 64))
+
+#define        __ELF_WORD_SIZE ELFSIZE
+#if (ELFSIZE == 32)
+#include <sys/elf32.h>
+#elif (ELFSIZE == 64)
+#include <sys/elf64.h>
+#endif
+#include <sys/elf_generic.h>
+
+#define CONCAT(x,y)     __CONCAT(x,y)
+#define ELFNAME(x)      CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
+#define ELFNAME2(x,y)   CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
+#define ELFNAMEEND(x)   CONCAT(x,CONCAT(_elf,ELFSIZE))
+#define ELFDEFNNAME(x)  CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
+
+struct listelem {
+       struct listelem *next;
+       void *mem;
+       off_t file;
+       size_t size;
+};
+
+static ssize_t
+xreadatoff(int fd, void *buf, off_t off, size_t size, const char *fn)
+{
+       ssize_t rv;
+
+       if (lseek(fd, off, SEEK_SET) != off) {
+               perror(fn);
+               return -1;
+       }
+       if ((rv = read(fd, buf, size)) != size) {
+               fprintf(stderr, "%s: read error: %s\n", fn,
+                   rv == -1 ? strerror(errno) : "short read");
+               return -1;
+       }
+       return size;
+}
+
+static ssize_t
+xwriteatoff(int fd, void *buf, off_t off, size_t size, const char *fn)
+{
+       ssize_t rv;
+
+       if (lseek(fd, off, SEEK_SET) != off) {
+               perror(fn);
+               return -1;
+       }
+       if ((rv = write(fd, buf, size)) != size) {
+               fprintf(stderr, "%s: write error: %s\n", fn,
+                   rv == -1 ? strerror(errno) : "short write");
+               return -1;
+       }
+       return size;
+}
+
+static void *
+xmalloc(size_t size, const char *fn, const char *use)
+{
+       void *rv;
+
+       rv = malloc(size);
+       if (rv == NULL)
+               fprintf(stderr, "%s: out of memory (allocating for %s)\n",
+                   fn, use);
+       return (rv);
+}
+
+int
+ELFNAMEEND(check)(int fd, const char *fn)
+{
+       Elf_Ehdr eh;
+       struct stat sb;
+
+       /*
+        * Check the header to maek sure it's an ELF file (of the
+        * appropriate size).
+        */
+       if (fstat(fd, &sb) == -1)
+               return 0;
+       if (sb.st_size < sizeof eh)
+               return 0;
+       if (read(fd, &eh, sizeof eh) != sizeof eh)
+               return 0;
+
+       if (IS_ELF(eh) == 0)
+                return 0;
+
+        switch (eh.e_machine) {
+       case EM_386: break;
+       case EM_ALPHA: break;
+/*        ELFDEFNNAME(MACHDEP_ID_CASES) */
+
+        default:
+                return 0;
+        }
+
+       return 1;
+}
+
+int
+ELFNAMEEND(hide)(int fd, const char *fn)
+{
+       Elf_Ehdr ehdr;
+       Elf_Shdr *shdrp = NULL, *symtabshdr, *strtabshdr;
+       Elf_Sym *symtabp = NULL;
+       char *strtabp = NULL;
+       Elf_Word *symfwmap = NULL, *symrvmap = NULL, nsyms, nlocalsyms, ewi;
+       struct listelem *relalist = NULL, *rellist = NULL, *tmpl;
+       ssize_t shdrsize;
+       int rv, i, weird;
+
+       rv = 0;
+       if (xreadatoff(fd, &ehdr, 0, sizeof ehdr, fn) != sizeof ehdr)
+               goto bad;
+
+       shdrsize = ehdr.e_shnum * ehdr.e_shentsize;
+       if ((shdrp = xmalloc(shdrsize, fn, "section header table")) == NULL)
+               goto bad;
+       if (xreadatoff(fd, shdrp, ehdr.e_shoff, shdrsize, fn) != shdrsize)
+               goto bad;
+
+       symtabshdr = strtabshdr = NULL;
+       weird = 0;
+       for (i = 0; i < ehdr.e_shnum; i++) {
+               switch (shdrp[i].sh_type) {
+               case SHT_SYMTAB:
+                       if (symtabshdr != NULL)
+                               weird = 1;
+                       symtabshdr = &shdrp[i];
+                       strtabshdr = &shdrp[shdrp[i].sh_link];
+                       break;
+               case SHT_RELA:
+                       tmpl = xmalloc(sizeof *tmpl, fn, "rela list element");
+                       if (tmpl == NULL)
+                               goto bad;
+                       tmpl->mem = NULL;
+                       tmpl->file = shdrp[i].sh_offset;
+                       tmpl->size = shdrp[i].sh_size;
+                       tmpl->next = relalist;
+                       relalist = tmpl;
+                       break;
+               case SHT_REL:
+                       tmpl = xmalloc(sizeof *tmpl, fn, "rel list element");
+                       if (tmpl == NULL)
+                               goto bad;
+                       tmpl->mem = NULL;
+                       tmpl->file = shdrp[i].sh_offset;
+                       tmpl->size = shdrp[i].sh_size;
+                       tmpl->next = rellist;
+                       rellist = tmpl;
+                       break;
+               }
+       }
+       if (symtabshdr == NULL)
+               goto out;
+       if (strtabshdr == NULL)
+               weird = 1;
+       if (weird) {
+               fprintf(stderr, "%s: weird executable (unsupported)\n", fn);
+               goto bad;
+       }
+
+       /*
+        * load up everything we need
+        */
+
+       /* symbol table */
+       if ((symtabp = xmalloc(symtabshdr->sh_size, fn, "symbol table"))
+           == NULL)
+               goto bad;
+       if (xreadatoff(fd, symtabp, symtabshdr->sh_offset, symtabshdr->sh_size,
+           fn) != symtabshdr->sh_size)
+               goto bad;
+
+       /* string table */
+       if ((strtabp = xmalloc(strtabshdr->sh_size, fn, "string table"))
+           == NULL)
+               goto bad;
+       if (xreadatoff(fd, strtabp, strtabshdr->sh_offset, strtabshdr->sh_size,
+           fn) != strtabshdr->sh_size)
+               goto bad;
+
+       /* any rela tables */
+       for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
+               if ((tmpl->mem = xmalloc(tmpl->size, fn, "rela table"))
+                   == NULL)
+                       goto bad;
+               if (xreadatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
+                   tmpl->size)
+                       goto bad;
+       }
+
+       /* any rel tables */
+       for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
+               if ((tmpl->mem = xmalloc(tmpl->size, fn, "rel table"))
+                   == NULL)
+                       goto bad;
+               if (xreadatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
+                   tmpl->size)
+                       goto bad;
+       }
+
+       /* Prepare data structures for symbol movement. */
+       nsyms = symtabshdr->sh_size / symtabshdr->sh_entsize;
+       nlocalsyms = symtabshdr->sh_info;
+       if ((symfwmap = xmalloc(nsyms * sizeof (Elf_Word), fn,
+           "symbol forward mapping table")) == NULL)
+               goto bad;
+       if ((symrvmap = xmalloc(nsyms * sizeof (Elf_Word), fn,
+           "symbol reverse mapping table")) == NULL)
+               goto bad;
+
+       /* init location -> symbol # table */
+       for (ewi = 0; ewi < nsyms; ewi++)
+               symrvmap[ewi] = ewi;
+
+       /* move symbols, making them local */
+       for (ewi = nlocalsyms; ewi < nsyms; ewi++) {
+               Elf_Sym *sp, symswap;
+               Elf_Word mapswap;
+
+               sp = &symtabp[ewi];
+
+               /* if it's on our keep list, don't move it */
+               if (in_keep_list(strtabp + sp->st_name))
+                       continue;
+
+               /* if it's an undefined symbol, keep it */
+               if (sp->st_shndx == SHN_UNDEF)
+                       continue;
+
+               /* adjust the symbol so that it's local */
+               sp->st_info =
+                   ELF_ST_INFO(STB_LOCAL, sp->st_info);
+/*                 (STB_LOCAL << 4) | ELF_SYM_TYPE(sp->st_info); *//* XXX */
+
+               /*
+                * move the symbol to its new location
+                */
+
+               /* note that symbols in those locations have been swapped */
+               mapswap = symrvmap[ewi];
+               symrvmap[ewi] = symrvmap[nlocalsyms];
+               symrvmap[nlocalsyms] = mapswap;
+
+               /* and swap the symbols */
+               symswap = *sp;
+               *sp = symtabp[nlocalsyms];
+               symtabp[nlocalsyms] = symswap;
+
+               nlocalsyms++;                   /* note new local sym */
+       }
+       symtabshdr->sh_info = nlocalsyms;
+
+       /* set up symbol # -> location mapping table */
+       for (ewi = 0; ewi < nsyms; ewi++)
+               symfwmap[symrvmap[ewi]] = ewi;
+
+       /* any rela tables */
+       for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
+               Elf_Rela *relap = tmpl->mem;
+
+               for (ewi = 0; ewi < tmpl->size / sizeof(*relap); ewi++) {
+                       relap[ewi].r_info =
+#if (ELFSIZE == 32)                                    /* XXX */
+                           symfwmap[ELF_R_SYM(relap[ewi].r_info)] << 8 |
+                           ELF_R_TYPE(relap[ewi].r_info);
+#elif (ELFSIZE == 64)                                  /* XXX */
+                           symfwmap[ELF_R_SYM(relap[ewi].r_info)] << 32 |
+                           ELF_R_TYPE(relap[ewi].r_info);
+#endif                                                 /* XXX */
+               }
+       }
+
+       /* any rel tables */
+       for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
+               Elf_Rel *relp = tmpl->mem;
+
+               for (ewi = 0; ewi < tmpl->size / sizeof *relp; ewi++) {
+                       relp[ewi].r_info =
+#if (ELFSIZE == 32)                                    /* XXX */
+                           symfwmap[ELF_R_SYM(relp[ewi].r_info)] << 8 |
+                           ELF_R_TYPE(relp[ewi].r_info);
+#elif (ELFSIZE == 64)                                  /* XXX */
+                           symfwmap[ELF_R_SYM(relp[ewi].r_info)] << 32 |
+                           ELF_R_TYPE(relp[ewi].r_info);
+#endif                                                 /* XXX */
+               }
+       }
+
+       /*
+        * write new tables to the file
+        */
+       if (xwriteatoff(fd, shdrp, ehdr.e_shoff, shdrsize, fn) != shdrsize)
+               goto bad;
+       if (xwriteatoff(fd, symtabp, symtabshdr->sh_offset,
+           symtabshdr->sh_size, fn) != symtabshdr->sh_size)
+               goto bad;
+       for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
+               if (xwriteatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
+                   tmpl->size)
+                       goto bad;
+       }
+       for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
+               if (xwriteatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
+                   tmpl->size)
+                       goto bad;
+       }
+
+out:
+       if (shdrp != NULL)
+               free(shdrp);
+       if (symtabp != NULL)
+               free(symtabp);
+       if (strtabp != NULL)
+               free(strtabp);
+       if (symfwmap != NULL)
+               free(symfwmap);
+       if (symrvmap != NULL)
+               free(symrvmap);
+       while ((tmpl = relalist) != NULL) {
+               relalist = tmpl->next;
+               if (tmpl->mem != NULL)
+                       free(tmpl->mem);
+               free(tmpl);
+       }
+       while ((tmpl = rellist) != NULL) {
+               rellist = tmpl->next;
+               if (tmpl->mem != NULL)
+                       free(tmpl->mem);
+               free(tmpl);
+       }
+       return (rv);
+
+bad:
+       rv = 1;
+       goto out;
+}
+
+#endif /* include this size of ELF */
diff --git a/usr.bin/crunch/crunchide/exec_elf64.c b/usr.bin/crunch/crunchide/exec_elf64.c
new file mode 100644 (file)
index 0000000..a0c0329
--- /dev/null
@@ -0,0 +1,39 @@
+/*     $NetBSD: exec_elf64.c,v 1.2 1997/08/02 21:30:19 perry Exp $     */
+
+/*
+ * Copyright (c) 1997 Christopher G. Demetriou.  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 Christopher G. Demetriou
+ *     for the NetBSD Project.
+ * 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.
+ *
+ * $NetBSD: exec_elf64.c,v 1.2 1997/08/02 21:30:19 perry Exp $
+ */
+
+#include <sys/cdefs.h>
+
+#define        ELFSIZE         64
+
+#include "exec_elf32.c"
diff --git a/usr.bin/crunch/crunchide/extern.h b/usr.bin/crunch/crunchide/extern.h
new file mode 100644 (file)
index 0000000..4de25a8
--- /dev/null
@@ -0,0 +1,70 @@
+/*     $NetBSD: extern.h,v 1.5 1998/05/06 13:16:57 mycroft Exp $       */
+/* $FreeBSD: src/usr.sbin/crunch/crunchide/extern.h,v 1.1.6.1 2002/07/25 09:33:17 ru Exp $ */
+/* $DragonFly: src/usr.sbin/crunch/crunchide/extern.h,v 1.2 2003/06/17 04:29:53 dillon Exp $ */
+
+/*
+ * Copyright (c) 1997 Christopher G. Demetriou.  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 Christopher G. Demetriou
+ *     for the NetBSD Project.
+ * 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.
+ */
+
+#ifdef arch_alpha
+#define        NLIST_ECOFF
+#define        NLIST_ELF64
+#else
+#ifdef arch_mips
+#define NLIST_ELF32
+#else
+#ifdef arch_powerpc
+#define        NLIST_ELF32
+#else
+#define        NLIST_AOUT
+/* #define     NLIST_ECOFF */
+#define        NLIST_ELF32
+/* #define     NLIST_ELF64 */
+#endif
+#endif
+#endif
+
+#ifdef NLIST_AOUT
+int    check_aout(int, const char *);
+int    hide_aout(int, const char *);
+#endif
+#ifdef NLIST_ECOFF
+int    check_ecoff(int, const char *);
+int    hide_ecoff(int, const char *);
+#endif
+#ifdef NLIST_ELF32
+int    check_elf32(int, const char *);
+int    hide_elf32(int, const char *);
+#endif
+#ifdef NLIST_ELF64
+int    check_elf64(int, const char *);
+int    hide_elf64(int, const char *);
+#endif
+
+int    in_keep_list(const char *symbol);
diff --git a/usr.bin/crunch/examples/Makefile b/usr.bin/crunch/examples/Makefile
new file mode 100644 (file)
index 0000000..861e302
--- /dev/null
@@ -0,0 +1,32 @@
+
+CRUNCHED=   fixit
+
+# below is boiler-plate to make $(CRUNCHED) from $(CRUNCHED).conf
+# I'd use PROG instead of CRUNCHED, but the system makefiles REALLY want
+# to build things in the normal way if you use PROG.
+
+CONF=  $(CRUNCHED).conf
+
+OUTMK= $(CRUNCHED).mk
+OUTPUTS=  $(OUTMK) $(CRUNCHED).c $(CRUNCHED).cache
+
+NOMAN=
+CLEANFILES+=$(CRUNCHED) *.o *.lo *.c *.mk *.cache
+CLEANDIRFILES+=$(OUTPUTS)
+
+all: $(CRUNCHED)
+exe: $(CRUNCHED)
+
+$(OUTPUTS): $(CONF)
+       crunchgen ${.CURDIR}/$(CONF)
+
+$(CRUNCHED): $(OUTPUTS) submake
+
+submake:
+       make -f $(OUTMK)
+objs:
+       make -f $(OUTMK) objs
+cleandir:
+       rm -f $(CLEANDIRFILES)
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/crunch/examples/filesystem.conf b/usr.bin/crunch/examples/filesystem.conf
new file mode 100644 (file)
index 0000000..d4315aa
--- /dev/null
@@ -0,0 +1,32 @@
+# $FreeBSD: src/usr.sbin/crunch/examples/filesystem.conf,v 1.8 1999/08/28 01:15:57 peter Exp $
+# $DragonFly: src/usr.sbin/crunch/examples/filesystem.conf,v 1.2 2003/06/17 04:29:53 dillon Exp $
+
+srcdirs /usr/src/bin /usr/src/sbin /usr/src/gnu/usr.bin /usr/src/usr.sbin
+srcdirs /usr/src/sbin/i386
+
+# /bin
+progs sh expr ls mkdir rm sync test
+ln test [
+
+# These are needed because of UN*X's idiotic way of indicating that something
+# is a login shell.
+ln sh -
+ln sh -sh
+
+# /sbin
+progs disklabel fdisk init mount newfs reboot umount
+ln reboot halt
+ln reboot fastboot
+ln reboot fasthalt
+
+
+# /usr/bin
+progs cpio gzip
+ln gzip gunzip
+ln gzip gzcat
+ln gzip zcat
+
+# /usr/sbin
+progs bad144
+
+libs -ll -ledit -ltermcap -lutil -lscrypt
diff --git a/usr.bin/crunch/examples/fixit.conf b/usr.bin/crunch/examples/fixit.conf
new file mode 100644 (file)
index 0000000..26543c3
--- /dev/null
@@ -0,0 +1,45 @@
+# fixit.conf - put in anything we think we might want on a fixit floppy
+
+# first, we list the source dirs that our programs reside in.  These are
+# searched in order listed to find the dir containing each program.
+
+srcdirs /usr/src/bin /usr/src/sbin /usr/src/usr.bin /usr/src/usr.sbin
+srcdirs /usr/src/gnu/usr.bin /usr/src/usr.bin/vi
+srcdirs /usr/src/sbin/i386
+
+# second, we list all the programs we want to include in our crunched binary.
+# The order doesn't matter.  Any program that needs hard links to it gets an
+# `ln' directive.
+
+# /bin stuff
+
+progs cat chmod cp date dd df echo ed expr hostname kill ln ls mkdir
+progs mt mv pwd rcp rm rmdir sh sleep stty sync test
+
+ln test [
+ln sh -sh              # init invokes the shell this way
+
+# /sbin stuff
+
+progs badsect chown clri disklabel dump dmesg fdisk fsck ifconfig init
+progs mknod mount newfs ping reboot restore swapon umount
+ln dump rdump
+ln restore rrestore
+
+# /usr/bin stuff
+
+progs ftp rsh sed telnet rlogin common find
+ln common vi
+ln common view
+ln common ex
+
+# gnu stuff
+
+progs cpio gzip
+ln gzip gunzip
+ln gzip gzcat
+
+# finally, we specify the libraries to link in with our binary
+
+libs -lcrypt -ltelnet -lutil -ll
+libs -lcurses -ltermcap -ledit -lkvm
diff --git a/usr.bin/crunch/examples/kcopy.conf b/usr.bin/crunch/examples/kcopy.conf
new file mode 100644 (file)
index 0000000..a6c1bd1
--- /dev/null
@@ -0,0 +1,22 @@
+# $FreeBSD: src/usr.sbin/crunch/examples/kcopy.conf,v 1.7 1999/08/28 01:15:57 peter Exp $
+# $DragonFly: src/usr.sbin/crunch/examples/kcopy.conf,v 1.2 2003/06/17 04:29:53 dillon Exp $
+
+srcdirs /usr/src/bin /usr/src/sbin
+
+# Programs from bin/
+progs sh cp echo test
+ln test [
+
+# These are needed because of UN*X's idiotic way of indicating that something
+# is a login shell.
+ln sh -
+ln sh -sh
+
+#
+# Programs from sbin/
+progs mount mount_cd9660 fsck init reboot umount
+ln reboot halt
+ln reboot fastboot
+ln reboot fasthalt
+
+libs -ll -ledit -ltermcap -lcompat -lutil -lscrypt
diff --git a/usr.bin/crunch/examples/really-big.conf b/usr.bin/crunch/examples/really-big.conf
new file mode 100644 (file)
index 0000000..b9b543a
--- /dev/null
@@ -0,0 +1,149 @@
+# $FreeBSD: src/usr.sbin/crunch/examples/really-big.conf,v 1.2.6.1 2003/02/10 12:21:09 des Exp $
+# $DragonFly: src/usr.sbin/crunch/examples/really-big.conf,v 1.4 2008/02/17 19:51:54 swildner Exp $
+#
+# really-big.conf - just about everything, just for testing.
+#      This ends up having some good examples of the use of specials for
+#      those hard-to-reach programs.  I stopped when I got tired, but we
+#      could probably get even more stuff (like libexec stuff) in here.
+#
+#       This produces a 4608000 byte binary.  Pretty sick and twisted, eh?
+
+# =========================================================================
+
+srcdirs /usr/src/bin
+
+progs cat chmod cp csh date dd df domainname echo ed expr hostname kill
+progs ln ls mkdir mt mv ps pwd rcp rm rmail rmdir sh sleep stty sync test
+
+ln test [
+ln sh -sh
+
+
+# =========================================================================
+
+srcdirs /usr/src/sbin
+
+progs badsect bim clri disklabel dmesg dump dumpfs fdisk fsck halt
+progs ifconfig init mknod modload modunload mount mount_fdesc mount_isofs
+progs mount_lofs mount_msdos mount_portal mount_procfs mountd
+progs newfs nfsd nfsiod ping quotacheck reboot restore route routed savecore
+progs shutdown slattach swapon ttyflags tunefs umount
+# shell scripts: fastboot
+
+ln dump rdump
+ln restore rrestore
+
+
+# =========================================================================
+
+srcdirs /usr/src/usr.bin
+
+progs apropos ar asa at basename biff cal calendar cap_mkdb checknr chpass
+progs cksum cmp col colcrt colrm column comm compress crontab ctags cut
+progs dirname du env error expand false file find finger fmt fold fpr from
+progs fsplit fstat ftp getconf getopt gprof head hexdump id indent ipcrm
+progs ipcs join kdump ktrace last lastcomm leave lex lock logger locate
+progs login logname look m4 machine mail make man mesg mkfifo
+progs mkstr modstat more msgs netstat newsyslog nfsstat nice nm nohup
+progs pagesize passwd paste patch pr printenv printf quota ranlib
+progs renice rev rlogin rpcgen rpcinfo rsh rup ruptime rusers rwall rwho
+progs script sed showmount size soelim split strings strip su tail talk
+progs tcopy tee telnet tftp time tip tn3270 touch tput tr true tset tsort
+progs tty ul uname unexpand unifdef uniq units unvis users uudecode uuencode
+progs vacation vgrind vi vis vmstat w wall wc what whatis whereis who
+progs whois window write xargs xinstall xstr yacc yes ypcat ypmatch ypwhich
+
+# shell scripts: lorder mkdep shar which
+# problems: rdist uses libcompat.a(regex.o), which conflicts with
+#           libedit(readline.o) over regerror().
+
+# special requirements
+
+special locate srcdir /usr/src/usr.bin/locate/locate
+special tn3270 srcdir /usr/src/usr.bin/tn3270/tn3270
+
+
+# =========================================================================
+
+srcdirs /usr/src/usr.sbin
+
+progs ac accton amd arp bad144 catman chown chroot config config.new cron
+progs dev_mkdb edquota flcopy gettable grfinfo hilinfo htable inetd
+progs iostat iteconfig kvm_mkdb mrouted mtree named portmap pppd
+progs pstat pwd_mkdb quot quotaon rarpd rbootd repquota rmt rpc.bootparamd
+progs rwhod sa sliplogin slstats spray sysctl syslogd tcpdump
+progs traceroute trpt trsp update vipw vnconfig ypbind yppoll ypset
+
+special amd srcdir /usr/src/usr.sbin/amd/amd
+special amd objs vers.amd.o afs_ops.o am_ops.o clock.o util.o xutil.o efs_ops.o mapc.o info_file.o info_hes.o info_ndbm.o info_passwd.o info_nis.o info_union.o map.o srvr_afs.o srvr_nfs.o mntfs.o misc_rpc.o mount_fs.o mtab.o mtab_bsd.o nfs_ops.o nfs_prot_svc.o nfs_start.o nfs_subr.o opts.o pfs_ops.o rpc_fwd.o sched.o sfs_ops.o amq_svc.o amq_subr.o umount_fs.o host_ops.o nfsx_ops.o ufs_ops.o ifs_ops.o amd.o get_args.o restart.o wire.o
+
+
+srcdirs /usr/src/usr.sbin/lpr          # lpr subsystem
+progs lpr lpc lpq lprm pac lptest
+special lpr srcdir /usr/src/usr.sbin/lpr/lpr
+
+srcdirs /usr/src/usr.sbin/sendmail     # sendmail subsystem
+progs mailstats makemap praliases sendmail
+special sendmail srcdir /usr/src/usr.sbin/sendmail/src
+ln sendmail newaliases
+ln sendmail mailq
+
+srcdirs /usr/src/usr.sbin/timed                # timed & timedc
+progs timed timedc
+special timed srcdir /usr/src/usr.sbin/timed/timed
+
+srcdirs /usr/src/usr.sbin/yp           # yp subsystem
+progs ypbind ypwhich ypcat ypmatch ypset yppoll
+
+
+# =========================================================================
+
+srcdirs /usr/src/gnu/usr.bin
+
+progs bc cpio diff diff3 gas gawk grep gzip sdiff sort tar
+# shell scripts: send-pr
+
+srcdirs /usr/src/gnu/usr.bin/ld                # ldd and ldconfig
+progs ld ldd ldconfig
+
+# rcs stuff loses because there are cross dependencies between librcs.a and
+# the individual programs.  The solution would be to specify the objpaths
+# directly for each one, and include the full path to librcs.a each the
+# objpaths.
+
+# srcdirs /usr/src/gnu/usr.bin/rcs     # rcs subsystem
+# progs ci co ident merge rcs rcsclean rcsdiff rcsmerge rlog
+# # shell script: rcsfreeze
+# special rcs srcdir /usr/src/gnu/usr.bin/rcs/rcs
+# libs /usr/src/gnu/usr.bin/rcs/lib/obj/librcs.a
+
+# gdb loses too
+# progs gdb
+# special gdb srcdir /usr/src/gnu/usr.bin/gdb/gdb
+# libs /usr/src/gnu/usr.bin/gdb/bfd/obj/libbfd.a
+# libs /usr/src/gnu/usr.bin/gdb/readline/obj/libreadline.a
+# libs /usr/src/gnu/usr.bin/gdb/libiberty/obj/libiberty.a
+
+# groff has the same problem as rcs
+# srcdirs /usr/src/gnu/usr.bin/groff   # groff subsystem
+# progs groff troff tbl pic eqn grops grotty grodvi refer lookbib
+# progs indxbib lkbib tfmtodit addftinfo pfbtops psbb
+# shell script: nroff
+# special groff srcdir /usr/src/gnu/usr.bin/groff/groff
+# libs /usr/src/gnu/usr.bin/groff/libgroff/obj/libgroff.a
+# libs /usr/src/gnu/usr.bin/groff/libbib/obj/libbib.a
+# libs /usr/src/gnu/usr.bin/groff/libdriver/obj/libdriver.a
+
+srcdirs /usr/src/gnu/usr.bin/gcc2      # gcc & friends
+progs cc cpp cc1
+
+# cc1 has the same problem as rcs and groff, but since there's only one program
+# I'll go ahead and solve it as an example.
+
+special cc1 objpaths /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-parse.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-lang.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-lex.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-pragma.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-decl.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-typeck.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-convert.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-aux-info.o /usr/src/gnu/usr.bin/gcc2/cc1/obj/c-iterate.o /usr/src/gnu/usr.bin/gcc2/common/obj/libcc1.a
+
+ln gzip gunzip
+ln gzip gzcat
+
+libs -ledit -lgnumalloc -lc -lcrypt -ltermcap -lcurses -ltelnet -lutil -lkvm
+libs -ll -ly -lm -lresolv -lrpcsvc -lcompat
index 738dfd3..2ed18d4 100644 (file)
@@ -7,6 +7,17 @@
 SRCDIR=                ${.CURDIR}/../../contrib/nvi
 SUBDIR+=       catalog
 
+.if defined(RELEASE_CRUNCH)
+# When building `vi' for the fixit floppy, don't include any of the
+# API stuff.
+APISTUFF=      ex_notcl.c ex_noperl.c
+
+.else
+
+APISTUFF=      ex_tcl.c ex_perl.c
+
+.endif
+
 WARNS?=        0       # some warn issues on 32 bit machines
 
 VI=    nvi
index df47797..9a6bbc6 100644 (file)
@@ -50,7 +50,7 @@ LDADD+=${WPA_SUPPLICANT_LDADD}
 SRCS+= eapol_supp_sm.c eap.c eap_common.c eap_methods.c
 CFLAGS+= -DIEEE8021X_EAPOL
 
-.if !defined(NO_CRYPT) && !defined(NO_OPENSSL)
+.if !defined(NO_CRYPT) && !defined(NO_OPENSSL) && !defined(RELEASE_CRUNCH)
 CFLAGS+=-DEAP_TLS -DEAP_PEAP -DEAP_MSCHAPv2 -DEAP_LEAP -DEAP_PSK \
        -DEAP_TLV -DEAP_TLS_FUNCS -DEAP_TLS_OPENSSL
 SRCS+= chap.c crypto_openssl.c \
index 6cadb66..56a491f 100644 (file)
@@ -7,10 +7,14 @@ SRCS= inetd.c builtins.c
 MAN=   inetd.8
 MLINKS=        inetd.8 inetd.conf.5
 
-CFLAGS+= -DLOGIN_CAP -DINET6 -DIPSEC
+CFLAGS+= -DLOGIN_CAP
 #CFLAGS+= -DSANITY_CHECK
 
-DPADD+=        ${LIBUTIL} ${LIBWRAP} ${LIBIPSEC}
-LDADD+=        -lutil -lwrap -lipsec
-
+DPADD+=        ${LIBUTIL} ${LIBWRAP}
+LDADD+=        -lutil -lwrap
+.if !defined(RELEASE_CRUNCH)
+CFLAGS+=-DINET6 -DIPSEC
+DPADD+=        ${LIBIPSEC}
+LDADD+=        -lipsec
+.endif
 .include <bsd.prog.mk>
index 930c84b..a21d11b 100644 (file)
@@ -8,6 +8,15 @@ SRCS=  acf.c arp.c async.c auth.c bundle.c cbcp.c ccp.c chap.c chat.c \
        mbuf.c mp.c ncp.c ncpaddr.c pap.c physical.c pred.c probe.c prompt.c \
        proto.c route.c server.c sig.c slcompress.c sync.c systems.c tcp.c \
        tcpmss.c throughput.c timer.c tty.c tun.c udp.c vjcomp.c
+.if defined(RELEASE_CRUNCH)
+CFLAGS+=-DRELEASE_CRUNCH
+NOATM=         true
+NOI4B=         true
+NONAT=         true
+NOKLDLOAD=     true
+NORADIUS=      true
+NOSUID=                true
+.endif
 
 .if defined(NOSUID) || defined(PPP_NOSUID)
 BINMODE=554
index a0a24be..98a2738 100644 (file)
@@ -677,9 +677,12 @@ bundle_LockTun(struct bundle *bundle)
   if (lockfile != NULL) {
     fprintf(lockfile, "%d\n", (int)getpid());
     fclose(lockfile);
-  } else
+  }
+#ifndef RELEASE_CRUNCH
+  else
     log_Printf(LogERROR, "Warning: Can't create %s: %s\n",
                pidfilename, strerror(errno));
+#endif
 }
 
 static void
index bf4433f..23f4396 100644 (file)
@@ -369,9 +369,13 @@ physical_Close(struct physical *p)
 
   if (*p->name.full == '/') {
     snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base);
+#ifndef RELEASE_CRUNCH
     if (ID0unlink(fn) == -1)
       log_Printf(LogALERT, "%s: Can't remove %s: %s\n",
                  p->link.name, fn, strerror(errno));
+#else
+    ID0unlink(fn);
+#endif
   }
   physical_Unlock(p);
   if (p->handler && p->handler->destroy)
@@ -976,9 +980,12 @@ physical_Found(struct physical *p)
     if (lockfile != NULL) {
       fprintf(lockfile, "%s%d\n", TUN_NAME, p->dl->bundle->unit);
       fclose(lockfile);
-    } else
+    }
+#ifndef RELEASE_CRUNCH
+    else
       log_Printf(LogALERT, "%s: Can't create %s: %s\n",
                  p->link.name, fn, strerror(errno));
+#endif
   }
 
   throughput_start(&p->link.stats.total, "physical throughput",
index 15b813e..dccc679 100644 (file)
@@ -29,11 +29,20 @@ LDADD+=     -lpcap
 DPADD+=        ${LIBPCAP}
 
 # MS-CHAP support.  Requires the DES library.
-.if exists(${.CURDIR}/../../secure) && !defined(NO_CRYPT)  && !defined(NO_OPENSSL)
+.if exists(${.CURDIR}/../../secure) && !defined(NO_CRYPT)  && !defined(NO_OPENSSL) && !defined(RELEASE_CRUNCH)
 CFLAGS+=-DCHAPMS
 SRCS+= chap_ms.c
 LDADD+=        -lcrypto
 DPADD+=        ${LIBCRYPTO}
 .endif
 
+.if defined(RELEASE_CRUNCH)
+# We must create these objects because crunchgen will link them,
+# and we don't want any unused symbols to spoil the final link.
+SRCS+= chap_ms.c
+chap_ms.o:
+       >null_${.PREFIX}.c
+       cc -c -o ${.TARGET} null_${.PREFIX}.c
+.endif
+
 .include <bsd.prog.mk>
index 9b8d8d8..2f28722 100644 (file)
@@ -64,7 +64,7 @@ SRCS+=        sm_os.h
 CLEANFILES+=sm_os.h
 
 .if exists(${.CURDIR}/../../secure) && !defined(NO_CRYPT) && \
-       !defined(NO_OPENSSL)
+       !defined(NO_OPENSSL) && !defined(RELEASE_CRUNCH)
 # STARTTLS support
 CFLAGS+=       -DSTARTTLS -D_FFR_TLS_1
 LDADD+=                -lssl -lcrypto
index d0f3d09..fe7d41d 100644 (file)
@@ -51,7 +51,8 @@ CFLAGS+=      -DINET6 -DHAVE_GETNAMEINFO
 
 DPADD= ${LIBL} ${LIBPCAP}
 LDADD= -ll -lpcap
-.if exists(../../secure) && !defined(NO_CRYPT) && !defined(NO_OPENSSL)
+.if exists(../../secure) && !defined(NO_CRYPT) && !defined(NO_OPENSSL) && \
+       !defined(RELEASE_CRUNCH)
 DPADD+= ${LIBCRYPTO}
 LDADD+= -lcrypto
 CFLAGS+= -I${DESTDIR}/usr/include/openssl -DHAVE_LIBCRYPTO -DHAVE_OPENSSL_EVP_H