summaryrefslogtreecommitdiff
path: root/pat
diff options
context:
space:
mode:
Diffstat (limited to 'pat')
-rw-r--r--pat/Jmakefile68
-rw-r--r--pat/Makefile.SH269
-rw-r--r--pat/README120
-rw-r--r--pat/pat.SH154
-rw-r--r--pat/pat.man513
-rw-r--r--pat/patbase.SH122
-rw-r--r--pat/patchlevel.h31
-rw-r--r--pat/patcil.SH541
-rw-r--r--pat/patclean.SH185
-rw-r--r--pat/patcol.SH235
-rw-r--r--pat/patdiff.SH236
-rw-r--r--pat/patftp.SH118
-rw-r--r--pat/patindex.SH66
-rw-r--r--pat/patlog.SH390
-rw-r--r--pat/patmake.SH413
-rw-r--r--pat/patname.SH175
-rw-r--r--pat/patnotify.SH232
-rw-r--r--pat/patpost.SH179
-rw-r--r--pat/patsend.SH218
-rw-r--r--pat/patsnap.SH124
20 files changed, 4389 insertions, 0 deletions
diff --git a/pat/Jmakefile b/pat/Jmakefile
new file mode 100644
index 0000000..c9ab104
--- /dev/null
+++ b/pat/Jmakefile
@@ -0,0 +1,68 @@
+/*
+ * Jmakefile for patching tools.
+ */
+
+;# $Id: Jmakefile,v 3.0.1.3 1995/07/24 09:57:21 ram Exp $
+;#
+;# Copyright (c) 1991-1993, Raphael Manfredi
+;#
+;# You may redistribute only under the terms of the Artistic Licence,
+;# as specified in the README file that comes with the distribution.
+;# You may reuse parts of this distribution only within the terms of
+;# that same Artistic Licence; a copy of which may be found at the root
+;# of the source tree for dist 3.0.
+;#
+;# $Log: Jmakefile,v $
+;# Revision 3.0.1.3 1995/07/24 09:57:21 ram
+;# patch56: was missing an entry for the patlog program
+;#
+;# Revision 3.0.1.2 1994/01/24 13:42:48 ram
+;# patch16: added dependency generation stage
+;#
+;# Revision 3.0.1.1 1993/08/24 12:09:05 ram
+;# patch3: added patnotify and patsnap
+;#
+;# Revision 3.0 1993/08/18 12:10:32 ram
+;# Baseline for dist 3.0 netwide release.
+;#
+
+/* BASE is used to give the extensions for pat* files. Usually, '//' can be
+ * used to specify a null expansion pattern, but some of those new smart cpp
+ * now think it's a up-to-end-of-line comment--why do they do that to us?
+ */
+BASE = /^^/ cil base diff make clean col name ftp send \
+ index post notify snap log
+
+/* PAT is derived from BASE and is the list of all the files to produce */
+PAT = \
+|expand f!$(BASE)!
+ pat!f \
+-expand \\
+
+NoManPages() /* There is a single man page for all tools */
+SimpleShellScriptTarget($(PAT))
+
+>SCRIPTDIR /* Grrr... I have to find a nicer way!! */
+>MANSRC /* Idem!! */
+
+InstallMultipleFlags($(PAT),$(SCRIPTDIR),-m 555)
+InstallManPage(pat,$(MANSRC))
+
+PATSH = \
+|expand f!$(PAT)!
+ !f.SH \
+-expand \\
+
+>SED
+>RM
+>MKDEP
+
+depend::
+ ($(SED) '/^# DO NOT DELETE/q' Makefile && \
+ grep '^\$$grep' $(PATSH) | \
+ $(SED) -e "s/^.*' \([^ ]*\) >>\([^ ]*\)/\2: \1/" \
+ ) > Makefile.new
+ cp Makefile Makefile.bak
+ cp Makefile.new Makefile
+ $(RM) Makefile.new
+
diff --git a/pat/Makefile.SH b/pat/Makefile.SH
new file mode 100644
index 0000000..1ae2c3d
--- /dev/null
+++ b/pat/Makefile.SH
@@ -0,0 +1,269 @@
+: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 3.0 PL55]
+: $X-Id: Jmake.tmpl,v 3.0.1.2 1995/01/11 14:50:21 ram Exp ram $
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+CURRENT=pat
+DIR=`echo $CURRENT/ | sed -e 's/\.\///g'`
+echo "Extracting ${DIR}Makefile (with variable substitutions)"
+
+INSTALL=`echo $install | sed -e 's,\./i,\$(TOP)/i,'`
+DATE=`date`
+
+$spitshell >Makefile <<!GROK!THIS!
+########################################################################
+# Makefile generated from Makefile.SH on $DATE
+
+SHELL = /bin/sh
+JMAKE = jmake
+TOP = ..
+CURRENT = $CURRENT
+DIR = $DIR
+INSTALL = $INSTALL
+
+########################################################################
+# Parameters set by Configure -- edit config.sh if changes are needed
+
+CTAGS = ctags
+L = $manext
+MANSRC = $installmansrc
+MAKE = make
+MKDEP = $mkdep \$(DPFLAGS) --
+MV = $mv
+RM = $rm -f
+SCRIPTDIR = $installscript
+SED = $sed
+
+!GROK!THIS!
+$spitshell >>Makefile <<'!NO!SUBS!'
+########################################################################
+# Jmake rules for building libraries, programs, scripts, and data files
+# $X-Id: Jmake.rules,v 3.0.1.3 1995/03/21 08:35:28 ram Exp ram $
+########################################################################
+# Force 'make depend' to be performed first -- do not edit
+
+.FORCE_DEPEND::
+
+all:: .FORCE_DEPEND
+
+########################################################################
+# Start of Jmakefile
+
+# $X-Id: Jmakefile,v 3.0.1.3 1995/07/24 09:57:21 ram Exp ram $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# $X-Log: Jmakefile,v $
+# Revision 3.0.1.3 1995/07/24 09:57:21 ram
+# patch56: was missing an entry for the patlog program
+#
+# Revision 3.0.1.2 1994/01/24 13:42:48 ram
+# patch16: added dependency generation stage
+#
+# Revision 3.0.1.1 1993/08/24 12:09:05 ram
+# patch3: added patnotify and patsnap
+#
+# Revision 3.0 1993/08/18 12:10:32 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+BASE = // cil base diff make clean col name ftp send \
+ index post notify snap log
+
+PAT = \
+ pat \
+ patcil \
+ patbase \
+ patdiff \
+ patmake \
+ patclean \
+ patcol \
+ patname \
+ patftp \
+ patsend \
+ patindex \
+ patpost \
+ patnotify \
+ patsnap \
+ patlog
+
+all:: $(PAT)
+
+local_realclean::
+ $(RM) $(PAT)
+
+pat: pat.SH
+ /bin/sh pat.SH
+
+patcil: patcil.SH
+ /bin/sh patcil.SH
+
+patbase: patbase.SH
+ /bin/sh patbase.SH
+
+patdiff: patdiff.SH
+ /bin/sh patdiff.SH
+
+patmake: patmake.SH
+ /bin/sh patmake.SH
+
+patclean: patclean.SH
+ /bin/sh patclean.SH
+
+patcol: patcol.SH
+ /bin/sh patcol.SH
+
+patname: patname.SH
+ /bin/sh patname.SH
+
+patftp: patftp.SH
+ /bin/sh patftp.SH
+
+patsend: patsend.SH
+ /bin/sh patsend.SH
+
+patindex: patindex.SH
+ /bin/sh patindex.SH
+
+patpost: patpost.SH
+ /bin/sh patpost.SH
+
+patnotify: patnotify.SH
+ /bin/sh patnotify.SH
+
+patsnap: patsnap.SH
+ /bin/sh patsnap.SH
+
+patlog: patlog.SH
+ /bin/sh patlog.SH
+
+
+install:: $(PAT)
+ @case '${MFLAGS}' in *[i]*) set +e;; esac; \
+ for i in $(PAT); do \
+ (set -x; $(INSTALL) -c -m 555 $$i $(SCRIPTDIR)); \
+ done
+
+deinstall::
+ @case '${MFLAGS}' in *[i]*) set +e;; esac; \
+ for i in $(PAT); do \
+ (set -x; $(RM) $(SCRIPTDIR)/$$i); \
+ done
+
+install.man:: pat.man
+ $(INSTALL) -c -m 444 pat.man $(MANSRC)/pat.$(L)
+
+deinstall.man::
+ $(RM) $(MANSRC)/pat.$(L)
+
+PATSH = \
+ pat.SH \
+ patcil.SH \
+ patbase.SH \
+ patdiff.SH \
+ patmake.SH \
+ patclean.SH \
+ patcol.SH \
+ patname.SH \
+ patftp.SH \
+ patsend.SH \
+ patindex.SH \
+ patpost.SH \
+ patnotify.SH \
+ patsnap.SH \
+ patlog.SH
+
+depend::
+ ($(SED) '/^# DO NOT DELETE/q' Makefile && \
+ grep '^\$$grep' $(PATSH) | \
+ $(SED) -e "s/^.*' \([^ ]*\) >>\([^ ]*\)/\2: \1/" \
+ ) > Makefile.new
+ cp Makefile Makefile.bak
+ cp Makefile.new Makefile
+ $(RM) Makefile.new
+
+########################################################################
+# Common rules for all Makefiles -- do not edit
+
+emptyrule::
+
+clean: local_clean
+realclean: local_realclean
+clobber: local_clobber
+
+local_clean::
+ $(RM) core *~ *.o
+
+local_realclean:: local_clean
+
+local_clobber:: local_realclean
+ $(RM) Makefile config.sh
+
+Makefile.SH: Jmakefile
+ -@if test -f $(TOP)/.package; then \
+ if test -f Makefile.SH; then \
+ echo " $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \
+ $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \
+ fi; \
+ echo " $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \
+ $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \
+ else touch $@; exit 0; fi
+
+Makefile: Makefile.SH
+ /bin/sh Makefile.SH
+
+tags::
+ $(CTAGS) -w *.[ch]
+ $(CTAGS) -xw *.[ch] > tags
+
+local_clobber::
+ $(RM) tags
+
+########################################################################
+# Empty rules for directories with no sub-directories -- do not edit
+
+install::
+ @echo "install in $(CURRENT) done."
+
+deinstall::
+ @echo "deinstall in $(CURRENT) done."
+
+install.man::
+ @echo "install.man in $(CURRENT) done."
+
+deinstall.man::
+ @echo "deinstall.man in $(CURRENT) done."
+Makefiles::
+
+Makefiles.SH::
+
+########################################################################
+# Dependencies generated by make depend
+# DO NOT DELETE THIS LINE -- make depend relies on it
+
+# Put nothing here or make depend will gobble it up
+.FORCE_DEPEND::
+ @echo "You must run 'make depend' in $(TOP) first."; exit 1
+!NO!SUBS!
+chmod 644 Makefile
+$eunicefix Makefile
+
diff --git a/pat/README b/pat/README
new file mode 100644
index 0000000..20e15ec
--- /dev/null
+++ b/pat/README
@@ -0,0 +1,120 @@
+This is the root directory for pat tools.
+
+This directory contains an automatic patch generator. You must have RCS
+to use this. You must also have run packinit in the top level directory
+of your package to create a .package file.
+
+When you've modified a file in your package, the pat program is used to
+control the whole process. The other programs can be called by hand, but
+usually needn't be. Run pat from the top level directory of your package.
+
+The pat, patcil, patdiff, and patbase programs take a list of filenames as
+arguments. Alternately, a -a means all files listed in MANIFEST.
+
+Patcil will create an RCS directory if necessary. However, it may not check in
+things which require special initializaton properly. For example, if you
+want to check in a shell script, you'd better make your RCS directory yourself
+and then say
+
+ rcs -i -c'# ' blurfl.xsh
+
+before running pat or patcil. Otherwise the RCS log may not be commented
+properly. Unless of course you are using a standard extension (like .c for
+a C file) or have placed the proper comments in front of the $Log marker
+within the file itself--patcil will then correctly guess the type of
+comment required.
+
+Patdiff will create a bugs directory in your top level directory, and will want
+to find a patchlevel.h file in that same directory. Everything is done from
+that top level directory--don't put any patchlevel.h or bugs directories in
+your subdirectories. Each subdirectory has its own RCS directory though.
+
+Patpost, patsend and patftp may be used to post to Usenet, mail to someone,
+or copy patches to your ftp directory. They take a destination and a list
+of patches to process.
+
+Those pat tools are an hopefully enhanced version of the tools that
+came with Larry Wall's dist 2.0. There are however a few new scripts:
+
+ - patclean, which checks in the mods and removes the working files.
+ - patcol, which restores the files removed by a patclean.
+ - patname, which sets a symbolic version number.
+
+Here is the way I am using the pat tools...
+
+First, I set up a MANIFEST.new file. If you are converting an existing
+distribution to use dist, the manifake script will convert a MANIFEST
+into a MANIFEST.new (removing the possible archive number column).
+
+Then I run packinit to modify the version number and set up things
+correctly. The package is then ready to be placed under pat control.
+I make sure the file patchlevel.h is correctly set and I run:
+
+ patcil -f -a -s
+ touch patchlevel.h
+ find . -name "*~" -exec /bin/rm -f {} \; -print
+
+There is a prototypical patchlevel.h file in this directory, so you
+might want to have a look at it.
+
+[If you are planning on using the mailagent to send the patches (and sort
+your mail -- that's its primary goal now), the you must make sure
+the patchelevel.h file is locatated in the root directory of your package.
+The mailagent program is available separately, and was posted on the
+comp.sources.misc newsgroup]
+
+Now everything is ready. The distribution is frozen, the bugs directory
+has been created. I issue a makedist -v to create the distribution kits.
+Eventually I set up the mailagent so that people can request for the
+distribution automatically. If I want to create a directory containing
+the lattest sources (to be able to `kit' them to someone using the kit
+program -- posted to comp.sources.unix), I use:
+
+ makedist -c <package>-<version>@<patchlevel>
+
+for instance, for dist 2.9 at PL26
+
+ makedist -c dist-2.9@26
+
+which I can then send to people directly with kit (which is NOT part
+of this release).
+
+As I receive patches or find some bugs, I edit the files and make the
+modifications. When I want to issue an official patch, I run:
+
+ pat -n
+
+and one or more patches are issued. You can compress the patches in the
+bugs subdirectory, since the mailpatch program knows about that. Also
+patindex will correctly uncompress them.
+
+When I need to clean up the distribution directory, I use:
+
+ patclean -a
+
+which checks in every changes and removes the working files. The whole
+set of working files can then be restored by:
+
+ patcol -a
+
+Sometimes, I made a couple of modification and I don't want to issue
+a patch right now. I then run:
+
+ patcil -a
+
+which checks in the changes. You can run this as many times as you want,
+because patcil will skip unchanged file and remembers the last time you
+issued a patch.
+
+If you are still using RCS 4.3, be sure you use makedist and not your
+own shell archiver, as the $Locker symbol has an annoying expansion
+which makes patch to fail when applyed. I'm not sure this was correctly
+fixed with RCS 5.5 as I am not using it yet for various reasons.
+
+In any case, if you are using the copyright expansion feature (i.e. the
+stuffing of the COPYRIGHT token surrounded by '@' -- can't do it here
+or it will get expanded...), then you must use makedist to make sure
+the copyright is properly written in all your files. Distributing files
+with an un-expanded COPYRIGHT token in them would be a disaster, since
+the patching system will also expand them before building a patch and
+some of your hunks may not apply correctly.
diff --git a/pat/pat.SH b/pat/pat.SH
new file mode 100644
index 0000000..946bf9d
--- /dev/null
+++ b/pat/pat.SH
@@ -0,0 +1,154 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/pat (with variable substitutions)"
+cat >pat <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: pat.SH,v 3.0.1.5 1994/10/29 16:37:53 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# Original Author: Larry Wall <lwall@netlabs.com>
+#
+# $Log: pat.SH,v $
+# Revision 3.0.1.5 1994/10/29 16:37:53 ram
+# patch36: now unlinks all the files created by patlog in bugs
+#
+# Revision 3.0.1.4 1994/01/24 14:29:17 ram
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.3 1993/08/25 14:04:35 ram
+# patch6: removal of patch temporary files did not work with gaps
+#
+# Revision 3.0.1.2 1993/08/24 12:14:39 ram
+# patch3: now removes older patch temporary files within bugs
+#
+# Revision 3.0.1.1 1993/08/19 06:42:31 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:36 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+cat >>pat <<'!NO!SUBS!'
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless $#ARGV >= 0;
+&usage unless &Getopts("ahmnV");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+&readpackage;
+
+if (-f 'patchlevel.h') {
+ open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n";
+ while (<PL>) {
+ $bnum = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/;
+ }
+ die "$progname: malformed patchlevel.h file.\n" if $bnum eq '';
+ ++$bnum;
+} else {
+ $bnum=1;
+}
+
+if ($opt_n) {
+ &newer; # Look for files newer than patchlevel.h
+} elsif ($opt_a) {
+ open(MANI,"MANIFEST.new") || die "No MANIFEST.new found.\n";
+ @ARGV = ();
+ while (<MANI>) {
+ s|^\./||;
+ next if m|^patchlevel.h|; # This file is built by hand
+ chop;
+ ($_) = split(' ');
+ next if -d;
+ push(@ARGV,$_);
+ }
+ close MANI;
+} elsif ($opt_m) {
+ open(MODS,"bugs/.mods$bnum") || die "$progname: no modification found.\n";
+ @ARGV = ();
+ while (<MODS>) {
+ next if m|^patchlevel.h$|; # This file is built by hand
+ chop;
+ ($_) = split(' ');
+ push(@ARGV,$_);
+ }
+ close MODS;
+}
+
+# Remove older patch temporary files
+
+@patlist = &patseq($bnum - 1);
+foreach $cpat (@patlist) {
+ unlink <bugs/*.$cpat bugs/.logs$cpat bugs/.mods$cpat bugs/.xlog$cpat>;
+ unlink <bugs/.pri$cpat bugs/.subj$cpat bugs/.clog$cpat bugs/.rlog$cpat>;
+}
+
+# Since we're about to launch other pat exectuables, disable ~/.dist_profile
+# to protect them if they added some weird switches we don't need...
+
+$ENV{'DIST'} = '/dev/null'; # Disable ~/.dist_profile
+
+system 'perl', '-S', 'patcil', '-p', @ARGV;
+
+# Update MANIFEST if necessary, then patcil it.
+
+if (-f 'MANIFEST' && `diff MANIFEST.new MANIFEST 2>/dev/null` ne '') {
+ system 'cp', 'MANIFEST.new', 'MANIFEST';
+ system 'perl', '-S', 'patcil', '-p', 'MANIFEST';
+ push(@ARGV, 'MANIFEST');
+}
+
+system 'perl', '-S', 'patdiff', @ARGV;
+system 'perl', '-S', 'patmake';
+
+sub usage {
+ print STDERR "Usage: $progname [-ahmnV] [filelist]\n";
+ print STDERR " -a : all the files in MANIFEST.new\n";
+ print STDERR " -h : print this message and exit\n";
+ print STDERR " -m : all the modified files (which have been patciled)\n";
+ print STDERR " -n : all the files newer than patchlevel.h\n";
+ print STDERR " -V : print version number and exit\n";
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/newer.pl >>pat
+$grep -v '^;#' ../pl/package.pl >>pat
+$grep -v '^;#' ../pl/patseq.pl >>pat
+$grep -v '^;#' ../pl/tilde.pl >>pat
+$grep -v '^;#' ../pl/profile.pl >>pat
+chmod +x pat
+$eunicefix pat
diff --git a/pat/pat.man b/pat/pat.man
new file mode 100644
index 0000000..05e9ac0
--- /dev/null
+++ b/pat/pat.man
@@ -0,0 +1,513 @@
+.rn '' }`
+''' $Id: pat.man,v 3.0.1.7 1997/02/28 16:32:45 ram Exp $
+'''
+''' Copyright (c) 1991-1993, Raphael Manfredi
+'''
+''' You may redistribute only under the terms of the Artistic Licence,
+''' as specified in the README file that comes with the distribution.
+''' You may reuse parts of this distribution only within the terms of
+''' that same Artistic Licence; a copy of which may be found at the root
+''' of the source tree for dist 3.0.
+'''
+''' $Log: pat.man,v $
+''' Revision 3.0.1.7 1997/02/28 16:32:45 ram
+''' patch61: documents contents of the message sent by patnotify
+'''
+''' Revision 3.0.1.6 1995/09/25 09:20:41 ram
+''' patch59: new -i option for patsend to add extra instructions
+'''
+''' Revision 3.0.1.5 1995/05/12 12:25:28 ram
+''' patch54: updated my e-mail address
+'''
+''' Revision 3.0.1.4 1994/10/29 16:38:31 ram
+''' patch36: documents new patlog script and the files it uses
+''' patch36: the RCS layer section has been extended slightly
+'''
+''' Revision 3.0.1.3 1993/08/27 14:40:19 ram
+''' patch7: random cleanup
+'''
+''' Revision 3.0.1.2 1993/08/25 14:05:02 ram
+''' patch6: new -q option for patsend and patnotify
+'''
+''' Revision 3.0.1.1 1993/08/24 12:15:42 ram
+''' patch3: added patnotify and patsnap
+''' patch3: patcol has a new -S option
+''' patch3: the users file built by mailagent is now listed under FILES
+'''
+''' Revision 3.0 1993/08/18 12:10:37 ram
+''' Baseline for dist 3.0 netwide release.
+'''
+.de Sh
+.br
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+'''
+.ie n \{\
+.tr \(*W-\*(Tr
+.ds -- \(*W-
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+.ds L' '
+.ds R' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds L' `
+.ds R' '
+'br\}
+.TH PAT 1 ram
+.SH NAME
+pat \- patch generator tools
+.SH SYNOPSIS
+.B pat
+[
+.B \-ahmnV
+] [
+.I filelist
+]
+.br
+.B patcil
+[
+.B \-abfhnpqsV
+] [
+.I filelist
+]
+.br
+.B patdiff
+[
+.B \-ahnV
+] [
+.I filelist
+]
+.br
+.B patbase
+[
+.B \-ahV
+] [
+.I filelist
+]
+.br
+.B patlog
+[
+.B \-hnruV
+]
+.br
+.B patmake
+[
+.B \-hV
+]
+.br
+.B patsend
+[
+.B \-hiquV
+] [
+.I patchlist
+] [
+.I recipients
+]
+.br
+.B patnotify
+[
+.B \-hquV
+] [
+.I recipients
+]
+.br
+.B patpost
+[
+.B \-hrV
+]
+.I patchlist
+.I newsgroups
+.br
+.B patftp
+[
+.B \-hV
+] [
+.I patchlist
+]
+.br
+.B patname
+[
+.B \-ahnmV
+]
+.B \-v
+.I version
+[
+.I filelist
+]
+.br
+.B patsnap
+[
+.B \-ahV
+] [
+.B \-o
+.I snapshot
+] [
+.I filelist
+]
+.br
+.B patcol
+[
+.B \-achnmsCV
+] [
+.B \-d
+.I directory
+] [
+.B \-f
+.I mani
+] [
+.B \-S
+.I snap
+] [
+.I filelist
+]
+.br
+.B patclean
+[
+.B \-ahnmV
+] [
+.I filelist
+]
+.br
+.B patindex
+.SH DESCRIPTION
+.I Pat
+and its associated programs generate patches for any package that has been
+stored under RCS.
+These programs hide many of the details of RCS that get in your way when
+constructing and maintaining a package.
+All you need to do to create a new patch is to edit your files, run pat,
+and furnish some descriptions to RCS and in the generated patch file.
+Details such as how to initialize a new RCS file, what the comment string should
+be, how create a new branch,
+how to deal with subdirectories, how to do diffs and how to
+organize the patch file are handled automatically.
+.PP
+Before using any of the pat programs you must initialize your package by
+running packinit in the top-level directory of your package.
+This produces a .package file that all of the dist programs make use of.
+.PP
+In any of the programs that want a filelist, if you specify
+.B \-a
+instead,
+all files in MANIFEST.new will be processed.
+In any of the programs that want a patchlist, a null patchlist means the
+current patch.
+You may use hyphens, commas and spaces to delimit patch numbers.
+If the right side of a hyphen is the null string, the current patchlevel
+is assumed as the maximum value. All the programs invoked with \fB\-h\fR
+will print a small usage message with the meaning of each available options.
+The \fB\-V\fR option gives the current version number.
+.PP
+Pat itself is a wrapper program that calls patcil, patdiff, and patmake.
+Usually you can just invoke pat and ignore all the others.
+Pat will update the MANIFEST file, if necessary (it will be an
+exact copy of the MANIFEST.new file, provided that a MANIFEST already
+existed), eventually calling patcil on it.
+.PP
+If you specify
+.B \-n
+instead of a filelist, pat will find all files that are
+newer than patchlevel.h, put you into an editor to trim down the list,
+then use that file list.
+If every file of the list is removed, \fIpat\fR will be aborted.
+.PP
+.I Patcil
+is used to do a ci -l on any listed files.
+(It is assumed that you always want to keep your files checked out.)
+In addition to the
+.B \-a
+switch, there is a
+.B \-b
+switch which does a quick checkin of
+a set of files.
+Instead of calling rcs on each file, it calls rcs on the whole list of
+files.
+This is useful for checking in a trunk revision.
+When you are checking in a new trunk revision you might also want to use
+the
+.B \-s
+flag which will strip out old RCS Log entries from the previous revision
+so that you can start over fresh.
+You probably should also use a
+.B \-f
+which is passed through to the ci to force unchanged files to be checked in.
+To check in a new trunk revision, I say
+.nf
+
+ patcil -s -f -a
+
+.fi
+.PP
+Patcil will ask for the log entry instead of letting ci do it, and has a little
+prompter built in that lets you manipulate the message in various ways.
+Type h for a listing of what you can do.
+One of the nicest things is that you can pop up into an editor, optionally
+with a diff listing of the changes since the last patch, in case you've
+forgotten what you changed.
+If you type a CR as the first thing, it includes the
+previous log message.
+Exit the prompter with a CR.
+.PP
+There are two different ways to use patcil.
+You can either call patcil yourself, or let pat call it for you.
+It doesn't matter how many times you call patcil before running pat, since
+patdiff knows what the last patch base is to compare with.
+Patcil can be called in any of your directories; the other programs must
+be called in your top-level directory (or in bugs, when meaningful).
+.PP
+When you are creating a new file at a given patchlevel, you must patcil it
+with the
+.B \-p
+option. Otherwise, it will simply be checked-in as
+a new trunk revision. The name of the file will be added to the MANIFEST.new
+if it does not already appear in it. If the name is found along with a
+description, that description will be passed through to rcs to properly
+initialize the RCS file.
+.PP
+.I Patbase
+can be used to reset the patch base to the current version when
+you've scrapped the previous patch sequence and are making a new distribution
+kit.
+What it really does is an rcs -Nlastpat:REV, where REV is the current
+revision.
+If patdiff blows up and you want to set the patch base back to some previous
+version, you have to call rcs -Nlastpat:REV yourself.
+.PP
+.I Patdiff
+actually does the diffs that go into the patch, comparing whatever
+version -Nlastpat points to with the most recently checked in version.
+It then updates -Nlastpat to point to the current version.
+It leaves the diff sitting in the bugs subdirectory for patmake to pick up.
+It can either use rcsdiff, or a diff command of your choice specified when
+you run packinit, in case your diff is better than rcsdiff.
+.PP
+.I Patlog
+is invoked by \fIpatmake\fR usually, to update the \fIChangeLog\fR file
+(or whatever name that file has been given when you ran \fIpackinit\fR).
+It will gather log messages and launch an editor for you to make the
+necessary updates.
+If you have configured your package to also include RCS logs
+in the \fIChangeLog\fR, another editor session will be launched for those
+too. Finally, a final log is built as a candidate entry for \fIChangeLog\fR,
+which you may also modify as you wish.
+.PP
+When you don't have configured a \fIChangeLog\fR file, \fIpatlog\fR will only
+gather the information it needs to pass on to \fIpatmake\fR and will exit.
+If you wish to call it yourself, you must do that after a least one
+sucessfull \fIpatdiff\fR run. I recommend using the \fB\-n\fR option the
+first time, and then use the \fB\-u\fR option along with \fB\-n\fR on
+subsequent runs to recreate files only when needed. The \fB\-r\fR option
+(which supersedes \fB\-u\fR) prevents \fIpatlog\fR from recreating an
+existing file, even if it is out of date.
+.PP
+.I Patlog
+will call \fIpatcil\fR and \fIpatdiff\fR on your \fIChangeLog\fR file
+(after having stuffed the candidate log entry you edited at the top of the
+file), unless prevented to do so by the \fB\-n\fR option. This means the
+issued patch will update \fIChangeLog\fR with current patch information, as
+you would expect it.
+.PP
+.I Patmake
+combines all the pieces of the patch into one file and invokes
+an editor so you can add the subject and description.
+It throws all your log messages in as Subjects and as Description, under
+the assumption
+that it's easier to delete what you don't want than to remember everything
+you did.
+You'll also want to expand each item in the Description so they don't just
+repeat the Subject lines. If you have a \fIChangeLog\fR file, this must have
+been done already, or your \fIChangeLog\fR will not accurately represent
+what is described in the patch, given that it has already been updated
+when \fIpatmake\fR puts together all the pieces (see the note
+about \fIpatlog\fR above).
+.PP
+Big patches will be split in order to keep size of each patch to a reasonable
+size. This is handled automatically, so you don't have to bother with it.
+The priority of each patch is merely intuited by \fIpatmake\fR, given the
+assumption that small changes have a great priority.
+.PP
+Patsend, patpost and patftp are used to distribute your patches to the world.
+.I Patsend
+mails a set of patches to a set of recipients. The \fB\-u\fR switch adds all
+the currently registered users who have asked for patches to be mailed to
+them, as well as the recipients specified while running \fIpackinit\fR.
+The \fB\-i\fR switch includes information with the patch about how the user
+may deregister themselves so they do not receive future patches automatically;
+this is also the default when the \fB\-u\fR switch is used.
+.I Patpost
+posts a set of patches to a set of newsgroups.
+.I Patftp
+merely copies the patch into your public ftp directory.
+.PP
+.I Patnotify
+simply notifies users that a new patch has been released so that
+they can retrieve it by themselves from an archive site or via e-mail if they
+are interested. The \fB\-u\fR switch can be used to include all the currently
+registered users who have asked for such a notification. The message includes
+the patch priority and description, as well as instructions on how to
+automatically request the patch (which will work only if you
+have \fImailagent\fR installed).
+.PP
+Both \fIpatsend\fR and \fIpatnotify\fR let you edit the address list before
+actually sending anything, unless you add the \fB\-q\fR option.
+.PP
+.I Patname
+can be used to tag a set of files with a symbolic name (specified with
+\fB\-v\fR). This will set the name for the most recent revision of each
+file.
+.PP
+.I Patsnap
+will get a snapshot of your release by creating a SNAPSHOT file (name can be
+changed via \fB\-o\fR) listing the file names and the latest RCS revision
+number for that file. Such snapshots can be used to identify the release
+at some random patchlevel and then later be able to retrieve it by feeding
+the snapshot file to \fIpatcol\fR.
+.PP
+.I Patcol
+will check out a locked version of a file, eventually in an alternate
+directory (specified with \fB\-d\fR, thus mirroring the distribution tree).
+All the files which have no RCS counterpart (e.g. patchlevel.h) will be
+simply copied by patcol. This is used by makedist to fake the distribution
+before making the kits. By default, patcol will not do the copyright expansion
+processing, but clients like \fImakedist\fR force it by using its \fB\-C\fR
+option. Alternatively, you may force copying of the checked-out version
+into a directory by using the \fB\-c\fR switch in conjunction with \fB\-d\fR
+(or that former switch is simply ignored).
+.PP
+.I Patcol
+can also take its file list from a SNAPSHOT file via the \fB\-S\fR switch, in
+which case it will check out the files using the RCS version specified by the
+snapshot file, such as one created by \fIpatsnap\fR. You may instead specify
+\fB-a\fR, \fB\-m\fR or \fB\-n\fR to respectively use all the files in
+MANIFEST.new, all the modified files (the one which have been \fIpatcil\fRed),
+or all the files newer than \fIpatchlevel.h\fR.
+.PP
+.I Patclean
+will remove the working files after having checked in all the
+changes. You may restores your working files by using patcol.
+.PP
+.I Patindex
+may be used from the top level directory or within the \fIbugs\fR directory.
+It will list all the patches and their \fISubject:\fR lines. This program
+knows about compressed patches and will decompress them while producing
+the listing.
+'''
+''' R C S L a y e r
+'''
+.SH RCS LAYER
+This section describes the RCS layer, in case something in the tools breaks,
+so that you may fix your RCS files and restart the operation.
+.PP
+All the patch tools get the main RCS trunk revision number out of your
+\&\fI.package\fR files, say it's 2.5. Then, at the time you ran \fIpackinit\fR,
+you have chosen a branch for patches, usually number 1, which means all your
+modifications will be stored on the 2.5.1 RCS branch. The tools will create
+the branch for you when the time comes.
+.PP
+Each last released revision is tagged with an RCS \fIlastpat\fR symbol. When
+the patch is built by \fIpatdiff\fR, the lattest version on the 2.5.1 branch
+is compared with the one tagged as \fIlastpat\fR. This is why you may safely
+issue more than one \fIpatcil\fR beffore issuing the patch and still have
+it all worked out. Of course \fIpatdiff\fR will move the \fIlastpat\fR
+tag to the lattest branch revision after processing a given file.
+.PP
+All the log messages and the modified files are kept in your \fIbugs\fR
+directory, in hidden files (name starting with a dot). Those logs will be
+collected when the patch is issued and the modified files are used by
+\&\fIpat\fR's \fB\-m\fR switch.
+.PP
+.I Patdiff
+collects its patch hunks under the \fIbugs\fR directory, in files
+terminating with a \fI.nn\fR extension, where \fInn\fR represents the
+current patch level + 1. (Which is going to be the next patchlevel when the
+patch will be made by \fIpatmake\fR, unless it is too big to fit in one
+file).
+.PP
+.I Patlog
+prepares a set of files for \fIpatmake\fR: the \fI.clog\fR file collects
+the information that will go under the Description: section within the
+patch, and \fI.xlog\fR ones collect the \fIChangeLog\fR candidate entry.
+Finally, \fI.rlog\fR files store the RCS information that is to be included
+in the \fIChangeLog\fR, if requested. Note that the topmost three lines
+are garbage and are ignored by all the tools handling those files.
+.PP
+In order to start up a new baseline (i.e. to change the RCS trunk revision
+number), you need to rerun \fIpackinit\fR and change that number. Then issue
+a new \fIpatcil\fR, probably with the \fB\-s\fR, \fB\-a\fR and \fB\-f\fR
+options...
+.SH FILES
+.PD 0
+.TP 15
+bugs/*.[0-9]+
+Diffs for each file, gathered by \fIpatmake\fR to create a patch
+.TP
+bugs/patch*
+Issued patches (can be compressed with \fIcompress\fR only)
+.TP
+bugs/.clog[0-9]+
+Description to be filled into the patch (or the first part if the patch is
+split into several parts).
+.TP
+bugs/.logs[0-9]+
+Log messages for that patch
+.TP
+bugs/.mods[0-9]+
+Files modified in that patch (checked in with \fIpatcil\fR)
+.TP
+bugs/.pri[0-9]+
+The priority of the next patch, computed
+by \fIpatlog\fR for \fIpatmake\fR's perusal.
+.TP
+bugs/.rlog[0-9]+
+The RCS logs computed by \fIpatlog\fR.
+.TP
+bugs/.subj[0-9]+
+The Subject: lines for the next patch, computed
+by \fIpatlog\fR for \fIpatmake\fR's perusal.
+.TP
+bugs/.xlog[0-9]+
+The candidate entry for \fIChangeLog\fR.
+.TP
+users
+File filled in by \fImailagent\fR's "@SH package" command, normally
+issued by Configure, recording some of the users who kindly registered
+themselves.
+.PD
+.SH ENVIRONMENT
+.PD 0
+.TP 15
+PAGER
+Which pager to use in patcil (overrides default)
+.TP
+EDITOR
+What editor should be used (overrides default)
+.TP
+VISUAL
+Same role as EDITOR but this one is checked first
+.PD
+.SH SEE ALSO
+makedist(1), metaconfig(1).
+.SH BUGS
+Most of this should be built into RCS.
+.SH AUTHORS
+Larry Wall (version 2.0).
+.br
+Raphael Manfredi <ram@hptnos02.grenoble.hp.com>.
+.rn }` ''
diff --git a/pat/patbase.SH b/pat/patbase.SH
new file mode 100644
index 0000000..7d67206
--- /dev/null
+++ b/pat/patbase.SH
@@ -0,0 +1,122 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patbase (with variable substitutions)"
+cat >patbase <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patbase.SH,v 3.0.1.3 1994/01/24 14:29:24 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# Original Author: Larry Wall <lwall@netlabs.com>
+#
+# $Log: patbase.SH,v $
+# Revision 3.0.1.3 1994/01/24 14:29:24 ram
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.2 1993/08/24 12:15:58 ram
+# patch3: random cleanup
+#
+# Revision 3.0.1.1 1993/08/19 06:42:32 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:38 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+cat >>patbase <<'!NO!SUBS!'
+
+$progname = &profile; # My name
+
+require 'getopts.pl';
+&usage unless $#ARGV >= 0;
+&usage unless &Getopts("ahV");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+&readpackage;
+
+$RCSEXT = ',v' unless $RCSEXT;
+$TOPDIR = ''; # We are at the top-level directory
+
+if ($opt_a) {
+ open(MANI,"MANIFEST.new") || die "No MANIFEST.new found.\n";
+ @ARGV = ();
+ while (<MANI>) {
+ chop;
+ s|^\./||;
+ next if m|^patchlevel.h|; # Special file
+ ($_) = split(' ');
+ next if -d;
+ push(@ARGV,$_);
+ }
+ close MANI;
+}
+
+foreach $file (@ARGV) {
+ $files = &rcsargs($file);
+ @files = split(' ',$files);
+ $revs=0;
+ $rlog = `rlog -r$baserev -r$revbranch $files 2>&1`;
+ ($revs) = ($rlog =~ /selected revisions: (\d+)/);
+ if (!$revs) {
+ print "$progname: $file has never been checked in--checking in...\n";
+ system 'perl', '-S', 'patcil', $file;
+ }
+ elsif ($revs == 1) {
+ print "Last revision for $file is $baserev.\n";
+ system 'rcs', "-Nlastpat:$baserev", @files;
+ }
+ else {
+ ($lastrev) = ($rlog =~ /revision $revbranch\.(\d+)/);
+ print "Last revision for $file is $revbranch.$lastrev.\n";
+ system 'rcs', "-Nlastpat:$revbranch.$lastrev", @files;
+ }
+}
+
+sub usage {
+ print STDERR "Usage: $progname [-ahV] [filelist]\n";
+ print STDERR " -a : all the files in MANIFEST.new\n";
+ print STDERR " -h : print this message and exit\n";
+ print STDERR " -V : print version number and exit\n";
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/package.pl >>patbase
+$grep -v '^;#' ../pl/rcsargs.pl >>patbase
+$grep -v '^;#' ../pl/comment.pl >>patbase
+$grep -v '^;#' ../pl/tilde.pl >>patbase
+$grep -v '^;#' ../pl/profile.pl >>patbase
+chmod +x patbase
+$eunicefix patbase
diff --git a/pat/patchlevel.h b/pat/patchlevel.h
new file mode 100644
index 0000000..7d282bb
--- /dev/null
+++ b/pat/patchlevel.h
@@ -0,0 +1,31 @@
+/*
+ * This is a prototypical patchlevel.h file. Only the line defining
+ * the PATCHLEVEL symbol is taken into account when patching, so be
+ * sure to make changes to this file ONLY when you start a new release
+ * and, of course, before running patcil...
+ *
+ * This file must appear in your MANIFEST.new, but it will never be
+ * checked in by the pat tools. It is automatically updated when a new
+ * patch is issued.
+ *
+ * When using the '-n' option in some pat* scripts, this file is
+ * taken as a timestamp. So it is best to avoid manual editing unless
+ * you know what you are doing.
+ */
+
+/*
+ * $Id: patchlevel.h,v 3.0 1993/08/18 12:10:39 ram Exp $
+ *
+ * Copyright (c) 1991, Raphael Manfredi
+ *
+ * You may redistribute only under the terms of the GNU General Public
+ * Licence as specified in the README file that comes with dist.
+ *
+ * $Log: patchlevel.h,v $
+ * Revision 3.0 1993/08/18 12:10:39 ram
+ * Baseline for dist 3.0 netwide release.
+ *
+ */
+
+#define VERSION 3.0 /* For instance */
+#define PATCHLEVEL 0 /* This line is a mandatory */
diff --git a/pat/patcil.SH b/pat/patcil.SH
new file mode 100644
index 0000000..ffcc069
--- /dev/null
+++ b/pat/patcil.SH
@@ -0,0 +1,541 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patcil (with variable substitutions)"
+$cat >patcil <<!GROK!THIS!
+$startperl
+ eval "exec perl -i~ -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patcil.SH,v 3.0.1.4 1994/10/29 16:42:12 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# Original Author: Larry Wall <lwall@netlabs.com>
+#
+# $Log: patcil.SH,v $
+# Revision 3.0.1.4 1994/10/29 16:42:12 ram
+# patch36: now honors the VISUAL and EDITOR environment variables
+# patch36: newer RCS programs chop trailing spaces in log messages
+# patch36: separated V/E and v/e commands
+# patch36: new 'v' command to edit the file being patcil'ed
+# patch36: added hook for 'V' command (not implemented yet)
+#
+# Revision 3.0.1.3 1994/01/24 14:30:04 ram
+# patch16: now prefix error messages with program's name
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.2 1993/08/25 14:05:35 ram
+# patch6: moved geteditor to ../pl/editor.pl
+#
+# Revision 3.0.1.1 1993/08/19 06:42:33 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:40 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+\$defeditor = '$defeditor';
+\$pager = '$pager';
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+cat >>patcil <<'!NO!SUBS!'
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless $#ARGV >= 0;
+&usage unless &Getopts("abfhnpqsV");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+$RCSEXT = ',v' unless $RCSEXT;
+$PAGER = $ENV{'PAGER'} || "$pager";
+$EDITOR = &geteditor;
+
+system 'mkdir', 'RCS' unless -d 'RCS';
+
+chop($pwd = `pwd`) unless -f '.package';
+until (-f '.package') {
+ die "$progname: no .package file! Run packinit.\n" unless $pwd;
+ chdir '..' || die "Can't cd ..";
+ $pwd =~ s|(.*)/(.*)|$1|;
+ $prefix = $2 . '/' . $prefix;
+}
+if ($prefix) {
+ for (@ARGV) {
+ s/^/$prefix/ unless m|^[-/]|;
+ }
+}
+
+# We now are at the top level
+
+&readpackage;
+
+if (-f 'patchlevel.h') {
+ open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n";
+ while (<PL>) {
+ $bnum = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/;
+ }
+ die "$progname: malformed patchlevel.h file.\n" if $bnum eq '';
+ ++$bnum;
+} else {
+ $bnum=1;
+}
+
+system 'mkdir', 'bugs' unless -d 'bugs';
+open(LOGS,">>bugs/.logs$bnum"); # Remember logs for patmake
+open(MODS,">>bugs/.mods$bnum"); # Remember modified files
+
+push(@sw,'-q') if $opt_q;
+push(@sw,'-f') if $opt_f;
+
+if ($opt_a) {
+ open(MANI,"MANIFEST.new") || die "$progname: can't read MANIFEST.new: $!\n";
+ @ARGV = ();
+ while (<MANI>) {
+ chop;
+ s|^\./||;
+ next if m|^patchlevel.h|; # Special file
+ ($_) = split(' ');
+ next if -d;
+ push(@ARGV,$_);
+ }
+ close MANI;
+} elsif ($opt_n) {
+ &newer;
+}
+
+@filelist = @ARGV;
+
+sub CLEANUP {
+ print "$progname: Warning: restore $ARGV\n";
+ exit 1;
+}
+
+if ($opt_s) {
+ open(TTY,">/dev/tty");
+ select(TTY);
+ $| = 1;
+ select(stdout);
+ $SIG{'INT'} = 'CLEANUP';
+ while (<>) {
+ if (/^(.*)\$Log[:\$]/) {
+ $comment = $1;
+ $comment =~ s/\s+$//; # Newer RCS chop spaces on emtpy lines
+ $len = length($comment);
+ print;
+ $lastnl = 1;
+ logline: while (<>) {
+ $c = substr($_,0,$len);
+ last logline unless $c eq $comment;
+ $_ = substr($_,$len,999);
+ if ($lastnl) {
+ unless (/^\s*Revision\s+\d/) {
+ $_ = $comment . $_;
+ last logline;
+ }
+ $lastnl = 0;
+ } else {
+ $lastnl = 1 if /^\s*$/;
+ }
+ }
+ }
+ }
+ continue {
+ print;
+ if ($ARGV ne $oldargv) {
+ print TTY "$progname: stripping $ARGV...\n";
+ $oldargv = $ARGV;
+ }
+ }
+ $SIG{'INT'} = 'DEFAULT';
+ close TTY;
+}
+
+if ($opt_b) {
+ $flist = &rcsargs(@filelist);
+ @flist=split(' ',$flist);
+ system 'rcs', '-u', @flist;
+ system 'rcs', "-l$revbranch", @flist;
+ system 'ci', '-l', "-r$revbranch", @sw, @flist;
+ exit 0;
+}
+
+open(MANI,"MANIFEST.new") || die "$progname: can't open MANIFEST.new: $!\n";
+while (<MANI>) {
+ # Find how many spaces the user wants before comments
+ $space || /(\S+\s+)\S+/ && ($space = length($1));
+ ($file,$file_comment) = m|(\S+)\s+(.*)|;
+ $inmani{$file} = 1; # File is listed in MANIFEST
+ $comment{$file} = $file_comment; # Save comments
+}
+close MANI;
+$space = 29 unless $space; # Default value
+
+file: foreach $file (@filelist) {
+ $files = &rcsargs($file);
+ @files = split(' ',$files);
+ $file = $files[1] if $file =~ /\.$RCSEXT$/;
+ unless ($inmani{$file}) {
+ print "$file does not appear to be in your MANIFEST.new--add? [y] ";
+ $ans = <stdin>;
+ if ($ans !~ /^n/i) {
+ print "MANIFEST.new comment? ";
+ $file_comment = <stdin>;
+ chop($file_comment);
+ $spacenum = $space - length($file);
+ $blank = " ";
+ $blank = " " x $spacenum unless $spacenum < 1;
+ `echo '${file}${blank}$file_comment' >>MANIFEST.new`;
+ if (-f 'MANIFEST') {
+ print "(Also adding file to your MANIFEST)\n";
+ # Add a (new) at the end, so the two manifests will
+ # differ and thus manifest will get patched correctly.
+ `echo '${file}${blank}$file_comment (new)' >>MANIFEST`;
+ print MODS "MANIFEST\n";
+ }
+ } else {
+ $file_comment = ""; # No file, no comment
+ }
+ }
+ $is_first = 0; # Suppose this is not the first cil
+ $revs = 0; # Makes revs a numeric variable
+ $rlog = `rlog -r$baserev -r$revbranch $files 2>&1`;
+ ($total) = ($rlog =~ /total revisions: (\d+)/);
+ ($revs) = ($rlog =~ /selected revisions: (\d+)/);
+ $comment = &rcscomment($file);
+ if (!$revs) {
+ if ($total) {
+ if ($rlog !~ /locks:\s*;/) {
+ system 'rcs', '-u', @files; # unlock branch
+ }
+ # New trunck revision
+ system 'rcs', '-l', @files; # lock trunk
+ }
+ else {
+ $file_comment = $comment{$file} if $inmani{$file};
+ if ($comment ne '') {
+ &feed($file_comment, 'rcs', '-i', "-c$comment", @files);
+ } else {
+ &feed($file_comment, 'rcs', '-i', @files);
+ }
+ }
+ if ($opt_p) { # check in null as trunk revision
+ rename($file, "$file.xxx");
+ `cp /dev/null $file` unless -f $file;
+ &cil_col("empty\n", $baserev);
+ system 'rcs', "-Nlastpat:$baserev", @files;
+ rename("$file.xxx", $file);
+ $mess = &getlog($file);
+ next file if $mess eq 'nope';
+ system 'rcs', '-u', @files; # Unlock trunck
+ &feed($mess, 'ci', "-l$revbranch", @sw, @files) unless $?;
+ } else {
+ $is_first = 1; # This is the first cil
+ $mess = &getlog($file);
+ next file if $mess eq 'nope';
+ &cil_col($mess, $baserev);
+ system 'rcs', "-Nlastpat:$baserev", @files;
+ }
+ } else {
+ if (!$opt_f) {
+ if ($revs == 1) {
+ $delta = `rcsdiff -r$baserev $files 2>/dev/null`;
+ } else {
+ $delta = `rcsdiff -r$revbranch $files 2>/dev/null`;
+ }
+ if ($delta eq '') { # No change in file
+ print "$progname: no changes in $file since last patcil.\n";
+ next; # Skip file
+ }
+ }
+ if ($revs == 1) {
+ $mess = &getlog($file);
+ next file if $mess eq 'nope';
+ &cil_cil($mess, $revbranch);
+ } else {
+ $mess = &getlog($file);
+ next file if $mess eq 'nope';
+ &cil_col($mess, $revbranch);
+ }
+ }
+}
+
+# Used for the first revisions on a branch
+sub cil_cil {
+ local($mess) = shift(@_);
+ local($rev) = shift(@_);
+ if (&feed($mess, 'ci', @sw, "-l$rev", @files)) {
+ print "$progname: unlocking and trying again...\n";
+ system 'rcs', '-u', @files;
+ &feed($mess, 'ci', @sw, "-l$rev", @files) unless $?;
+ }
+}
+
+# Run a ci -l on the file. If this fails, try to lock the file first.
+# If this fails again, try again with a separate checkout.
+sub cil_col {
+ local($mess) = shift(@_);
+ local($rev) = shift(@_);
+ if (&feed($mess, 'ci', @sw, "-l$rev", @files)) {
+ print "$progname: locking and trying again...\n";
+ if ($rev =~ /\d+\.\d+\.\d+/) {
+ system 'rcs', "-l$rev", @files; # Lock branch
+ } else {
+ system 'rcs', '-l', @files; # Lock trunck
+ }
+ if (&feed($mess, 'ci', @sw, "-l$rev", @files)) {
+ print "$progname: trying again with separate checkout...\n";
+ if (&feed($mess, 'ci', @sw, "-r$rev", @files)) {
+ system 'rcs', "-u$rev", @files unless $?;
+ system 'co', "-l$rev", @files unless $?;
+ } else {
+ print "$progname: sorry, giving up...\n";
+ }
+ }
+ }
+}
+
+sub feed {
+ local($mess) = shift(@_);
+ open(FORK,"|-") || exec @_;
+ print FORK $mess;
+ close FORK;
+ $?;
+}
+
+sub getlog {
+ local($file) = @_;
+ local($mess) = '';
+ local($prefix) = "patch$bnum: ";
+ local($prompt) = $comment;
+ local($len);
+ $prompt = '>> ' unless $prompt;
+ $prefix = '' if $is_first;
+ print "Type log message for $file (finish with ., CR for previous):\n";
+ try: for (;;) {
+ line: for (print "$prompt$prefix";;print "$prompt$prefix") {
+ if ($always) {
+ print "\n";
+ $line = '';
+ } else {
+ $line = <stdin>;
+ }
+ if ($line =~ /^\.?$/) {
+ if ($mess) {
+ last line;
+ } else {
+ $line = 'p';
+ }
+ }
+ if ($line =~ /^[h?]$/) {
+ print "
+CR or . Terminate log message.
+!<cmd> Start command in a subshell.
+D Print out diff listing since last patch.
+N Give name of the current file.
+E Call editor for log message with a diff listing.
+V Call editor for file with a context diff added to HISTORY.
+X Extract HISTORY and append it to current log message.
+a Always use this message.
+d Print out diff listing since last patcil.
+f Forget message I have so far.
+h or ? This help message.
+l List what I have so far.
+n Forget this file; go to next file if any.
+p Append previous message.
+r Print out the rlog for this file.
+e Call editor for log message.
+v Call editor for file.
+x Toggle patch# prefix.
+
+";
+ next line;
+ }
+ if ($line =~ /^!(.*)$/) {
+ $_ = $1;
+ $_ = ($ENV{'SHELL'} || "/bin/sh") if $1 eq '';
+ system $_;
+ next line;
+ }
+ if ($line =~ /^E$/) {
+ $mess .= "\n" . `rcsdiff -c -rlastpat $files`;
+ }
+ if ($line =~ /^e$/) {
+ $mess = &edit($mess);
+ next line;
+ }
+ if ($line =~ /^V$/) {
+ ######## FIXME #########
+ # Will do something like:
+ # &add_history($file, `rcsdiff -c -rlastpat $files`);
+ # HISTORY
+ # Extract or add this. Create it if not already there.
+ # $Log
+ # $EndLog <<-- stops HISTORY and COPYRIGHT lookup
+ ########################
+ print "HISTORY processing not implemented yet.\n";
+ print "(You have to use 'E' to get old 'V' processing).\n";
+ next line;
+ }
+ if ($line =~ /^v$/) {
+ system $EDITOR, $file;
+ next line;
+ }
+ if ($line =~ /^r$/) {
+ system "rlog $files | $PAGER";
+ next line;
+ }
+ if ($line =~ /^D$/) {
+ if ($revs == 0) {
+ print "Sorry. There is no revision for this file yet.\n";
+ } else {
+ system "rcsdiff -c -rlastpat $files | $PAGER";
+ }
+ next line;
+ }
+ if ($line =~ /^d$/) {
+ if ($revs == 0) {
+ print "Sorry. There is no revision for this file yet.\n";
+ }
+ elsif ($revs == 1) {
+ system "rcsdiff -c -r$baserev $files | $PAGER";
+ } else {
+ system "rcsdiff -c -r$revbranch $files | $PAGER";
+ }
+ next line;
+ }
+ if ($line =~ /^N$/) {
+ print "Typing log message for $file.\n";
+ next line;
+ }
+ if ($line =~ /^f$/) {
+ $mess = '';
+ next line;
+ }
+ if ($line =~ /^a$/) {
+ $always++ if $mess || $prevmess;
+ next line;
+ }
+ if ($line =~ /^n$/) {
+ $mess = 'nope';
+ last line;
+ }
+ if ($line =~ /^l$/) {
+ foreach $line (split(/\n/,$mess)) {
+ print $prompt,$line,"\n";
+ }
+ next line;
+ }
+ if ($line =~ /^p$/) {
+ $mess .= $prevmess;
+ foreach $line (split(/\n/,$prevmess)) {
+ print $prompt,$line,"\n";
+ }
+ next line;
+ }
+ if ($line =~ /^X$/) {
+ foreach $line (split(/\n/, &xtract_history($file))) {
+ $mess .= $prompt . $line . "\n";
+ print $prompt,$line,"\n";
+ }
+ next line;
+ }
+ if ($line =~ /^x$/) {
+ $prefix = $prefix ? '' : "patch$bnum: ";
+ next line;
+ }
+ $mess .= $prefix . $line;
+ $len = length($comment . $prefix . $line);
+ if ($len > 80) {
+ print "(Warning: last line longer than 80 chars)\n";
+ } elsif ($len > 72) { # In case of vi with line numbers
+ print "(Warning: last line longer than 72 chars)\n";
+ }
+ if (length($mess) > 511) {
+ print "You'll have to trim to less than 512 chars...\n";
+ sleep(3);
+ $mess = &edit($mess);
+ }
+ }
+ $mess = $prevmess if $mess eq '';
+ if (!$mess) {
+ print "No previous message, try again.\n";
+ next try;
+ }
+ if (length($mess) > 511) {
+ print "Sorry, that's too long; RCS won't take it. Try again...\n";
+ next try;
+ }
+ last try;
+ }
+ unless ($is_first) {
+ print LOGS $mess unless $mess eq 'nope';
+ print MODS "$file\n";
+ }
+ $prevmess = $mess unless $mess eq 'nope';
+ $mess; # Returned value
+}
+
+sub edit {
+ local($text) = join("\n", @_);
+ open(TMP,">/tmp/cil$$") || die "Can't create /tmp/cil$$";
+ print TMP $text;
+ close TMP;
+ system $EDITOR, "/tmp/cil$$";
+ $text = `cat /tmp/cil$$`;
+ unlink "/tmp/cil$$";
+ $text;
+}
+
+sub usage {
+ print STDERR <<EOM;
+Usage: $progname [-abfhnpqsV] [filelist]
+ -a : all the files in MANIFEST.new
+ -b : batch mode
+ -f : force check in (passed through to ci)
+ -h : print this message and exit
+ -n : all the files newer than patchlevel.h
+ -p : patching mode (null trunk revision if new file)
+ -q : ask rcs to be quiet
+ -s : strip log messages
+ -V : print version number and exit
+EOM
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/newer.pl >>patcil
+$grep -v '^;#' ../pl/package.pl >>patcil
+$grep -v '^;#' ../pl/rcsargs.pl >>patcil
+$grep -v '^;#' ../pl/comment.pl >>patcil
+$grep -v '^;#' ../pl/editor.pl >>patcil
+$grep -v '^;#' ../pl/tilde.pl >>patcil
+$grep -v '^;#' ../pl/profile.pl >>patcil
+chmod +x patcil
+$eunicefix patcil
diff --git a/pat/patclean.SH b/pat/patclean.SH
new file mode 100644
index 0000000..16947f1
--- /dev/null
+++ b/pat/patclean.SH
@@ -0,0 +1,185 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patclean (with variable substitutions)"
+cat >patclean <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patclean.SH,v 3.0.1.2 1994/01/24 14:30:17 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# $Log: patclean.SH,v $
+# Revision 3.0.1.2 1994/01/24 14:30:17 ram
+# patch16: now prefix error messages with program's name
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.1 1993/08/19 06:42:33 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:41 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+cat >>patclean <<'!NO!SUBS!'
+
+$RCSEXT = ',v' unless $RCSEXT;
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless $#ARGV >= 0;
+&usage unless &Getopts("ahnmV");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+$RCSEXT = ',v' unless $RCSEXT;
+$ENV{'DIST'} = '/dev/null'; # Disable ~/.dist_profile
+
+chop($pwd = `pwd`) unless -f '.package';
+until (-f '.package') {
+ die "$progname: no .package file! Run packinit.\n" unless $pwd;
+ chdir '..' || die "$progname: can't cd ..: $!\n";
+ $pwd =~ s|(.*)/(.*)|$1|;
+ $prefix = $2 . '/' . $prefix;
+}
+if ($prefix) {
+ for (@ARGV) {
+ s/^/$prefix/ unless m|^[-/]|;
+ }
+}
+
+# We now are at the top level
+
+&readpackage;
+
+if ($opt_n) {
+ &newer; # Look for files newer than patchlevel.h
+} elsif ($opt_a) {
+ open(MANI,"MANIFEST.new") || die "$progname: can't read MANIFEST.new: $!\n";
+ @ARGV = ();
+ while (<MANI>) {
+ s|^\./||;
+ next if m|^patchlevel.h|; # This file is built by hand
+ chop;
+ ($_) = split(' ');
+ next if -d;
+ push(@ARGV,$_);
+ }
+ close MANI;
+} elsif ($opt_m) {
+ open(MODS,"bugs/.mods$bnum") || die "$progname: no modification found.\n";
+ @ARGV = ();
+ while (<MODS>) {
+ next if m|^patchlevel.h$|; # This file is built by hand
+ chop;
+ ($_) = split(' ');
+ push(@ARGV,$_);
+ }
+ close MODS;
+}
+
+# Set a temporary file for check outs
+$TMPFILE = "/tmp/cl$$.tmp";
+
+# Now loop over each file specified, doing a 'rcsclean'
+foreach $file (@ARGV) {
+ if (-f $file) {
+ $files = &rcsargs($file);
+ @files = split(' ', $files);
+ $rlog = `rlog -rlastpat- $files 2>&1`;
+ ($revs) = ($rlog =~ /selected revisions: (\d+)/);
+ if (!$revs) {
+ print "$progname: $file has never been checked in--checking in...\n";
+ system 'perl', '-S', 'patcil', '-p', $file;
+ $revs = 2; # At least null trunk + new fresh revision
+ }
+ # Look whether there is a branch
+ if ($revs == 1) {
+ $rlog = `rlog -r$revbranch $files 2>&1`;
+ ($revs) = ($rlog =~ /selected revisions: (\d+)/);
+ $revs++; # add the base revision
+ }
+ # We must only give the name of the RCS revision file, i.e. $files[1]
+ if ($revs == 1) {
+ system "co -q -p$baserev $files[1] > $TMPFILE";
+ } else {
+ system "co -q -p$revbranch $files[1] > $TMPFILE";
+ }
+ if ($? == 0) {
+ system 'cmp', '-s', $file, $TMPFILE;
+ if ($? == 0) {
+ unlink $file;
+ print "$progname: $file removed.\n";
+ } else {
+ # Check in file and make sure all was ok
+ system 'perl', '-S', 'patcil', '-p', $file;
+ system "co -q -p$revbranch $files[1] > $TMPFILE";
+ if ($? == 0) {
+ system 'cmp', '-s', $file, $TMPFILE;
+ if ($? == 0) {
+ unlink $file;
+ print "$progname: $file removed.\n";
+ } else {
+ print "$progname: $file NOT removed.\n";
+ }
+ } else {
+ print "$progname: could not check out--$file NOT removed.\n";
+ }
+ }
+ } else {
+ print "$progname: no revision--$file NOT removed.\n";
+ }
+ }
+}
+
+unlink "$TMPFILE";
+
+sub usage {
+ print STDERR <<EOM;
+Usage: $progname [-ahnmV] [filelist]
+ -a : all the files in MANIFEST.new
+ -h : print this message and exit
+ -n : all the files newer than patchlevel.h
+ -m : all the modified files (which have been patciled)
+ -V : print version number and exit
+EOM
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/newer.pl >>patclean
+$grep -v '^;#' ../pl/package.pl >>patclean
+$grep -v '^;#' ../pl/rcsargs.pl >>patclean
+$grep -v '^;#' ../pl/tilde.pl >>patclean
+$grep -v '^;#' ../pl/profile.pl >>patclean
+chmod +x patclean
+$eunicefix patclean
diff --git a/pat/patcol.SH b/pat/patcol.SH
new file mode 100644
index 0000000..8cd0090
--- /dev/null
+++ b/pat/patcol.SH
@@ -0,0 +1,235 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patcol (with variable substitutions)"
+cat >patcol <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patcol.SH,v 3.0.1.3 1994/01/24 14:30:25 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# $Log: patcol.SH,v $
+# Revision 3.0.1.3 1994/01/24 14:30:25 ram
+# patch16: now prefix error messages with program's name
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.2 1993/08/24 12:16:30 ram
+# patch3: new -S option for snapshot check-outs
+#
+# Revision 3.0.1.1 1993/08/19 06:42:34 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:42 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+cat >>patcol <<'!NO!SUBS!'
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless $#ARGV >= 0;
+&usage unless &Getopts("acd:f:hnmsCRS:V");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+$RCSEXT = ',v' unless $RCSEXT;
+$NEWMANI = 'MANIFEST.new' unless $NEWMANI = $opt_f;
+
+chop($pwd = `pwd`) unless -f '.package';
+until (-f '.package') {
+ die "$progname: no .package file! Run packinit.\n" unless $pwd;
+ chdir '..' || die "$progname: can't cd ..: $!";
+ $pwd =~ s|(.*)/(.*)|$1|;
+ $prefix = $2 . '/' . $prefix;
+}
+if ($prefix) {
+ for (@ARGV) {
+ s/^/$prefix/ unless m|^[-/]|;
+ }
+}
+
+# We now are at the top level
+
+&readpackage;
+undef $opt_C unless -f $copyright;
+&copyright'init($copyright) if $opt_C;
+&makedir($opt_d) if $opt_d;
+
+undef $opt_c unless $opt_d; # Disable -c if not -d
+undef $opt_R unless $opt_d; # Disable -R if not -d
+push(@sw, '-q') if $opt_s; # Let RCS work quietly
+
+if ($opt_n) {
+ &newer; # Look for files newer than patchlevel.h
+} elsif ($opt_a) {
+ open(MANI, $NEWMANI) || die "No $NEWMANI found.\n";
+ @ARGV = ();
+ while (<MANI>) {
+ s|^\./||;
+ next if m|^patchlevel.h| && !$opt_d; # This file is built by hand
+ chop;
+ ($_) = split(' ');
+ next if -d;
+ push(@ARGV,$_);
+ }
+ close MANI;
+} elsif ($opt_m) {
+ open(MODS,"bugs/.mods$bnum") || die "$progname: no modification found.\n";
+ @ARGV = ();
+ while (<MODS>) {
+ next if m|^patchlevel.h$|; # This file is built by hand
+ chop;
+ ($_) = split(' ');
+ next if -d;
+ push(@ARGV,$_);
+ }
+ close MODS;
+} elsif ($opt_S) {
+ &readsnapshot($opt_S);
+ foreach $file (sort keys %Snap) {
+ push(@ARGV, $file);
+ }
+}
+
+# Now loop over each file specified, doing a 'co -l'
+foreach $file (@ARGV) {
+ if ($opt_c && -f $file) {
+ &copy_file($file, $opt_d);
+ next;
+ }
+ # Continue only if file does not exist or option -d was used.
+ if (! -f $file || $opt_d) {
+ $files = &rcsargs($file);
+ @files = split(' ', $files);
+ if ($opt_S && ($rev = $Snap{$file}) ne '') { # Use snapshot file
+ &col($rev);
+ next;
+ }
+ $rlog = `rlog -rlastpat- $files 2>&1`;
+ ($revs) = ($rlog =~ /selected revisions: (\d+)/);
+ if (!$revs) {
+ if ($opt_d) {
+ &copy_file($file, $opt_d);
+ } else {
+ print STDERR "$progname: $file has never been checked in\n";
+ }
+ } else {
+ # Look whether there is a branch
+ if ($revs == 1) {
+ $rlog = `rlog -r$revbranch $files 2>&1`;
+ ($revs) = ($rlog =~ /selected revisions: (\d+)/);
+ $revs++; # add the base revision (trunk)
+ }
+ if ($revs == 1) {
+ &col($baserev);
+ } else {
+ &col($revbranch);
+ }
+ }
+
+ }
+}
+
+# Run co -l on @files, unlock file if it fails and retry.
+# If '-d' option was used, we check out in the specified
+# directory, after having made all the necessary directories
+# in the path name (which should be relative to the top).
+sub col {
+ local($rev) = shift; # Revision to be checked out.
+ if (! $opt_d) {
+ if (system 'co', "-l$rev", @sw, @files) {
+ print "$progname: unlocking and trying again...\n" unless $opt_s;
+ system 'rcs', '-u', @sw, @files;
+ system 'co', "-l$rev", @sw, @files unless $?;
+ }
+ } else {
+ local($name) = $files[0]; # First element is file name
+ $_ = $name;
+ s|(.*)/.*|\1| && &makedir("$opt_d/$_");
+ if ($opt_C) {
+ &copyright'expand("co -p @sw -r$rev $files[1]", "$opt_d/$name");
+ } else {
+ system "co -p -r$rev @sw $files[1] > $opt_d/$name";
+ }
+ system 'perl', '-pi', '-e', 's|Lock[e]r:.*\$|\$|;', "$opt_d/$name"
+ if $opt_R;
+ # If RCS file has x bits set, add them on new file
+ -x $files[1] && chmod(0755, "$opt_d/$name");
+ }
+}
+
+# Copy file into directory, eventually performing copyright expansion...
+sub copy_file {
+ local($file, $dir) = @_;
+ local($base) = $file =~ m|^(.*)/.*|;
+ &makedir("$dir/$base");
+ if ($opt_C) {
+ &copyright'expand("cat $file", "$dir/$file");
+ } else {
+ system 'cp', "$file", "$dir/$file";
+ }
+ system 'perl', '-pi', '-e', 's|Lock[e]r:.*\$|\$|;', "$dir/$file" if $opt_R;
+ -x $file && chmod(0755, "$dir/$file");
+ print "$progname: $file has been copied\n" unless $opt_s;
+}
+
+sub usage {
+ print STDERR <<EOM;
+Usage: $progname [-achnmsCRV] [-d directory] [-f mani] [-S snap] [filelist]
+ -a : all the files in MANIFEST.new (see also -f)
+ -c : copy files if checked-out copy exists (only when -d)
+ -d : check out (or copy) in the specified directory
+ -f : use supplied file instead of MANIFEST.new
+ -h : print this message and exit
+ -n : all the files newer than patchlevel.h
+ -m : all the modified files (which have been patciled)
+ -s : silent mode
+ -C : perform copyright expansion on checked out (or copied) file
+ -R : strip out RCS \$Locker marker from checked-out file (only when -d)
+ -S : use snapshot file to determine file list and RCS revisions
+ -V : print version number and exit
+EOM
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/newer.pl >>patcol
+$grep -v '^;#' ../pl/package.pl >>patcol
+$grep -v '^;#' ../pl/rcsargs.pl >>patcol
+$grep -v '^;#' ../pl/copyright.pl >>patcol
+$grep -v '^;#' ../pl/makedir.pl >>patcol
+$grep -v '^;#' ../pl/snapshot.pl >>patcol
+$grep -v '^;#' ../pl/tilde.pl >>patcol
+$grep -v '^;#' ../pl/profile.pl >>patcol
+chmod +x patcol
+$eunicefix patcol
diff --git a/pat/patdiff.SH b/pat/patdiff.SH
new file mode 100644
index 0000000..a013aed
--- /dev/null
+++ b/pat/patdiff.SH
@@ -0,0 +1,236 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patdiff (with variable substitutions)"
+cat >patdiff <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patdiff.SH,v 3.0.1.2 1994/01/24 14:30:36 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# Original Author: Larry Wall <lwall@netlabs.com>
+#
+# $Log: patdiff.SH,v $
+# Revision 3.0.1.2 1994/01/24 14:30:36 ram
+# patch16: now prefix error messages with program's name
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.1 1993/08/19 06:42:35 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:43 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+cat >>patdiff <<'!NO!SUBS!'
+
+$RCSEXT = ',v' unless $RCSEXT;
+$TOPDIR = ''; # We are at top-level directory
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless $#ARGV >= 0;
+&usage unless &Getopts("ahnV");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+&readpackage;
+&copyright'init($copyright) if -f $copyright;
+
+system 'mkdir', 'bugs' unless -d 'bugs';
+
+if (-f 'patchlevel.h') {
+ open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n";
+ while (<PL>) {
+ $bnum = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/;
+ }
+ die "$progname: malformed patchlevel.h file.\n" if $bnum eq '';
+ ++$bnum;
+} else {
+ $bnum=1;
+}
+
+if ($opt_a) {
+ open(MANI,"MANIFEST.new") || die "$progname: can't read MANIFEST.new: $!\n";
+ @ARGV = ();
+ while (<MANI>) {
+ chop;
+ ($_) = split(' ');
+ next if -d;
+ push(@ARGV,$_);
+ }
+ close MANI;
+}
+
+foreach $file (@ARGV) {
+ next if ($file =~ /^patchlevel.h$/); # Skip patchlevel.h
+ if (! -f $file) {
+ print "$progname: $file not found.\n";
+ next;
+ }
+ $files = &rcsargs($file);
+ @files = split(' ',$files);
+ $new='';
+ $revs=0;
+ $rlog = `rlog -rlastpat- $files 2>&1`;
+ ($lastpat) = ($rlog =~ /lastpat: ([\d.]+)/);
+ ($revs) = ($rlog =~ /selected revisions: (\d+)/);
+ if (!$revs) {
+ print "$progname: no cil has been done on $file.\n" ;;
+ } elsif ($revs == 1) {
+ ($base) = ($rlog =~ /.*\nrevision\s+(\S+)/);
+ ($a,$b,$c,$d) = split(/\./,$base);
+ if ($d ne '') {
+ if (!$opt_n) {
+ print
+ "$progname: no changes in $file since last patch. (Did you cil it?)\n";
+ next; # Skip file with no changes
+ } else {
+ $new='foo';
+ }
+ } else {
+ $revs=0;
+ $rlog = `rlog -r$revbranch- $files 2>&1`;
+ ($revs) = ($rlog =~ /selected revisions: (\d+)/);
+ if (!$revs) {
+ print
+ "$progname: no changes in $file since base version. (Did you cil it?)\n";
+ next; # Skip file with no changes
+ } else {
+ ($new) = ($rlog =~ /\nrevision\s*(\d+\.\d+\.\d+\.\d+)/);
+ }
+ }
+ } else {
+ ($new) = ($rlog =~ /\nrevision\s*(\d+\.\d+\.\d+\.\d+)/);
+ }
+ if ($new ne '') {
+ ($fname = $file) =~ s|.*/||;
+ $fname = substr($fname, 0, 11); # For filsystems with short names
+ open(PATCH,">>bugs/$fname.$bnum") || die "Can't make patch";
+ print PATCH "\nIndex: $file\n";
+ open(CO,"co -p -rlastpat $files 2>/dev/null |");
+ while (<CO>) {
+ if (/\$Header/ || /\$Id/) {
+ print PATCH "Prereq: $lastpat\n";
+ last;
+ }
+ }
+ close CO;
+ if (!$opt_n) {
+ if ($mydiff eq '') {
+ open(DIFF,"rcsdiff -c -rlastpat -r$new $files |") ||
+ die "$progname: can't fork rcsdiff: $!\n";
+ while (<DIFF>) {
+ if ($. == 1) {s|\*\*\* \S+ |*** $file.old |;}
+ if ($. == 2) {s|--- \S+ |--- $file |;}
+ s|Lock[e]r:.*\$|\$|; # Use [e] to make it safe on itself
+ print PATCH;
+ }
+ close DIFF;
+ system 'rcs', "-Nlastpat:$new", @files;
+ } else {
+ &copyright'expand("co -p -rlastpat $file", "/tmp/pdo$$");
+ &copyright'expand("co -p -r$new $file", "/tmp/pdn$$");
+ open(DIFF, "$mydiff /tmp/pdo$$ /tmp/pdn$$ |") ||
+ die "Can't run $mydiff";
+ while (<DIFF>) { # Contextual or unified diff
+ if ($. == 1) {
+ s|\*\*\* \S+ |*** $file.old | ||
+ s|--- \S+ |--- $file.old |;
+ }
+ if ($. == 2) {
+ s|--- \S+ |--- $file | ||
+ s|\+\+\+ \S+ |+++ $file |;
+ }
+ s|Lock[e]r:.*\$|\$|; # Remove locker mark
+ print PATCH;
+ }
+ close DIFF;
+ system 'rcs', "-Nlastpat:$new", @files;
+ unlink "/tmp/pdn$$", "/tmp/pdo$$";
+ }
+ } else {
+ if ($mydiff eq '') {
+ open(DIFF,"rcsdiff -c -rlastpat $files |") ||
+ die "Can't run rcsdiff";
+ while (<DIFF>) {
+ if ($. == 1) {s|\*\*\* \S+ |*** $file.old |;}
+ if ($. == 2) {s|--- \S+ |--- $file |;}
+ s|Lock[e]r:.*\$|\$|; # Remove locker mark
+ print PATCH;
+ }
+ close DIFF;
+ } else {
+ system "co -p -rlastpat $files >/tmp/pdo$$";
+ system "cp $file /tmp/pdn$$";
+ open(DIFF, "$mydiff /tmp/pdo$$ /tmp/pdn$$ |") ||
+ die "$progname: can't fork $mydiff: $!\n";
+ while (<DIFF>) {
+ # Contextual or unified diff
+ if ($. == 1) {
+ s|\*\*\* \S+ |*** $file.old |;
+ s|--- \S+ |--- $file.old |;
+ }
+ if ($. == 2) {
+ s|--- \S+ |--- $file |;
+ s|\+\+\+ \S+ |+++ $file |;
+ }
+ s|Lock[e]r:.*\$|\$|; # Remove locker mark
+ print PATCH;
+ }
+ close DIFF;
+ unlink "/tmp/pdn$$", "/tmp/pdo$$";
+ }
+ }
+ }
+}
+
+sub usage {
+ print STDERR <<EOM;
+Usage: $progname [-ahnV] [filelist]
+ -a : all the files in MANIFEST.new
+ -h : print this message and exit
+ -n : non update mode
+ -V : print version number and exit
+EOM
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/package.pl >>patdiff
+$grep -v '^;#' ../pl/rcsargs.pl >>patdiff
+$grep -v '^;#' ../pl/copyright.pl >>patdiff
+$grep -v '^;#' ../pl/tilde.pl >>patdiff
+$grep -v '^;#' ../pl/profile.pl >>patdiff
+chmod +x patdiff
+$eunicefix patdiff
diff --git a/pat/patftp.SH b/pat/patftp.SH
new file mode 100644
index 0000000..73bd01e
--- /dev/null
+++ b/pat/patftp.SH
@@ -0,0 +1,118 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patftp (with variable substitutions)"
+cat >patftp <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patftp.SH,v 3.0.1.3 1994/01/24 14:30:43 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# Original Author: Larry Wall <lwall@netlabs.com>
+#
+# $Log: patftp.SH,v $
+# Revision 3.0.1.3 1994/01/24 14:30:43 ram
+# patch16: now prefix error messages with program's name
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.2 1993/08/24 12:16:57 ram
+# patch3: removed useless orgname variable
+#
+# Revision 3.0.1.1 1993/08/19 06:42:36 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:44 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+cat >>patftp <<'!NO!SUBS!'
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless &Getopts("hV");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+$RCSEXT = ',v' unless $RCSEXT;
+chdir '..' if -d '../bugs';
+
+&readpackage;
+
+if ($#ARGV < 0) {
+ open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n";
+ while (<PL>) {
+ $argv = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/;
+ }
+ close PL;
+ die "$progname: malformed patchlevel.h file.\n" if $argv eq '';
+ @ARGV = $argv;
+} else {
+ for (@ARGV) {
+ s/^patch//;
+ }
+ $argv = &rangeargs(@ARGV);
+ @ARGV = split(' ',$argv);
+}
+
+if ($#ARGV < 0) {
+ print STDERR "$progname: no patches specified.\n";
+ &usage;
+} elsif ($#ARGV) {
+ print "$progname: copying $package $baserev patches $argv to $ftpdir...\n";
+} else {
+ print "$progname: copying $package $baserev patch $argv to $ftpdir...\n";
+}
+
+chdir 'bugs' || die "$progname: can't cd to bugs: $!\n";
+
+until ($#ARGV < 0) {
+ $patnum = shift;
+ `cp patch$patnum $ftpdir`;
+}
+
+sub usage {
+ print STDERR <<EOM;
+Usage: $progname [-hV] patchlist
+ -h : print this message and exit
+ -V : print version number and exit
+EOM
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/package.pl >>patftp
+$grep -v '^;#' ../pl/rangeargs.pl >>patftp
+$grep -v '^;#' ../pl/tilde.pl >>patftp
+$grep -v '^;#' ../pl/profile.pl >>patftp
+chmod +x patftp
+$eunicefix patftp
diff --git a/pat/patindex.SH b/pat/patindex.SH
new file mode 100644
index 0000000..754d20e
--- /dev/null
+++ b/pat/patindex.SH
@@ -0,0 +1,66 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patindex (with variable substitutions)"
+$spitshell >patindex <<!GROK!THIS!
+$startsh
+
+# $Id: patindex.SH,v 3.0.1.1 1993/08/19 06:42:37 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# Original Author: Larry Wall <lwall@netlabs.com>
+#
+# $Log: patindex.SH,v $
+# Revision 3.0.1.1 1993/08/19 06:42:37 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:44 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+zcat='$zcat'
+test='$test'
+sed='$sed'
+grep='$grep'
+
+!GROK!THIS!
+$spitshell >>patindex <<'!NO!SUBS!'
+if test -d bugs; then
+ cd bugs
+fi
+for i in patch? patch??; do
+ if $test -f $i; then
+ echo "=== $i ==="
+ $grep '^Subject: ' $i | $sed 's/^patch\(.*\):Subject/\1/'
+ fi
+done
+for i in patch?.Z patch??.Z; do
+ if $test -f $i; then
+ name=`echo $i | $sed "s|\.Z$||"`
+ echo "=== $name ==="
+ $zcat $i | $grep '^Subject: ' | $sed 's/^patch\(.*\):Subject/\1/'
+ fi
+done
+!NO!SUBS!
+chmod 755 patindex
+$eunicefix patindex
diff --git a/pat/patlog.SH b/pat/patlog.SH
new file mode 100644
index 0000000..45059f6
--- /dev/null
+++ b/pat/patlog.SH
@@ -0,0 +1,390 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patlog (with variable substitutions)"
+cat >patlog <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patlog.SH,v 3.0.1.2 1997/02/28 16:33:03 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# $Log: patlog.SH,v $
+# Revision 3.0.1.2 1997/02/28 16:33:03 ram
+# patch61: typo fix
+#
+# Revision 3.0.1.1 1994/10/29 16:42:26 ram
+# patch36: created
+#
+
+\$defeditor='$defeditor';
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+cat >>patlog <<'!NO!SUBS!'
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless &Getopts("hnruV");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+&readpackage;
+
+if (-f 'patchlevel.h') {
+ open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n";
+ while (<PL>) {
+ if (/^#define\s+PATCHLEVEL\s+(\d+)/) {
+ $last = $1;
+ $patchline = $.; # Record PATCHLEVEL line
+ }
+ }
+ die "$progname: malformed patchlevel.h file.\n" if $last eq '';
+ $bnum = $last + 1;
+}
+else {
+ $patchline = 1;
+ $bnum = 1;
+ $last = '';
+}
+
+chdir 'bugs' if -d 'bugs';
+
+die "$progname: patch #$bnum already exists.\n" if -f "patch$bnum";
+
+@patlist=<*.$bnum>;
+die "$progname: no diff files for patch #$bnum.\n" if
+ $patlist[0] =~ /^\*/ || $patlist[0] eq '';
+
+# Set up a proper editor, for later perusal
+$editor = $ENV{'VISUAL'};
+$editor = $ENV{'EDITOR'} unless $editor;
+$editor = $defeditor unless $editor;
+$editor = 'vi' unless $editor;
+
+# The following used to be done in patmake. Only we do not really need to
+# compute the subject lines for the generated patch here, we do it nonetheless
+# to avoid code duplication in patmake.
+
+if (-s ".logs$bnum") {
+ $logs = '';
+ open(LOGS,".logs$bnum");
+ while (<LOGS>) {
+ unless ($logseen{$_}) {
+ $logs .= $_;
+ $logseen{$_}++;
+ $logsnum++; # One more log
+ }
+ }
+ close LOGS;
+ $* = 1;
+ $subj = $logs;
+ $logs =~ s/^patch\d+:\s*/\t/g;
+ $logs =~ s/\n/\n\n/g;
+ $subj =~ s/^patch\d+:\s*/Subject: /g;
+ $* = 0;
+} else {
+ $subj = "Subject: \n";
+}
+
+# Try to guess the priority of the patch
+if (-s ".mods$bnum") {
+ open(MODS, ".mods$bnum");
+ while (<MODS>) {
+ chop;
+ unless ($fileseen{$_}) {
+ $fileseen{$_}++;
+ $modsnum++; # One more modified file
+ }
+ }
+ close MODS;
+}
+$modsnum++ unless $modsnum; # Avoid divisions by zero
+$mean = $logsnum / $modsnum;
+if ($mean > 0.7 && $mean < 1.3) {
+ $priority = "MEDIUM";
+} elsif ($mean <= 0.7) {
+ $priority = "HIGH"; # Small changes
+} else {
+ $priority = "LOW"; # Big changes
+}
+
+# Save priority for patmake
+open(PRIORITY, ">.pri$bnum") || die "$progname: can't create .pri$bnum: $!\n";
+print PRIORITY $priority, "\n";
+close PRIORITY;
+
+# Save subject lines for patmake
+open(SUBJECTS, ">.subj$bnum") || die "$progname: can't create .subj$bnum: $!\n";
+print SUBJECTS $subj;
+close SUBJECTS;
+
+#
+# Generate description file, then edit it so that the user may fixup things.
+#
+
+unless (($opt_r && -f ".clog$bnum") || ($opt_u && &uptodate(".clog$bnum"))) {
+ open(CHANGES, ">.clog$bnum") ||
+ die "$progname: can't create .clog$bnum: $!\n";
+ print CHANGES <<EOM;
+Edition of the Description section for patch #$bnum.
+Please leave those three lines here, they will be removed automatically.
+------------------------------------------------------------------------
+EOM
+ print CHANGES $logs;
+ close CHANGES;
+}
+
+# If they don't want to maintain a ChangeLog file, that's it. They'll get
+# the old behaviour where the description is edited directly from within
+# the generated patch.
+
+exit(0) if $changelog =~ /^\s*$/;
+
+system $editor, ".clog$bnum";
+
+#
+# Generate RCS log file.
+#
+
+if ($changercs) {
+ unless (
+ ($opt_r && -f ".rlog$bnum") || ($opt_u && &uptodate(".rlog$bnum"))
+ ) {
+ &buildlogs;
+ open(RCS, ">.rlog$bnum") ||
+ die "$progname: can't create .rlog$bnum: $!\n";
+ print RCS <<EOM;
+Edition of the RCS log section for $changelog (patch #$bnum).
+Please leave those three lines here, they will be removed automatically.
+------------------------------------------------------------------------
+EOM
+ foreach $key (sort keys %rcslog) {
+ print RCS &format('* ' . $rcslog{$key}), "\n";
+ }
+ close RCS;
+ }
+ system $editor, ".rlog$bnum";
+}
+
+#
+# Final logfile entry generation
+#
+
+chop($date=`date`);
+
+unless (
+ ($opt_r && -f ".xlog$bnum") ||
+ ($opt_u && &uptodate(".xlog$bnum") && !&newertmp)
+) {
+ open(LOG, ">.xlog$bnum") || die "$progname: can't create .xlog$bnum: $!\n";
+ print LOG <<EOM;
+Edition of the $changelog entry for patch #$bnum.
+Please leave those three lines here, they will be removed automatically.
+------------------------------------------------------------------------
+EOM
+ print LOG "$date $maintname <$maintloc>\n\n";
+ print LOG ". Description:\n\n";
+ &addlog(".clog$bnum");
+ if ($changercs) {
+ print LOG ". Files changed:\n\n";
+ &addlog(".rlog$bnum");
+ }
+ close LOG;
+}
+system $editor, ".xlog$bnum";
+exit(0) if $opt_n;
+
+#
+# Changelog file update, checking in and diff computation.
+#
+
+print "$progname: updating $changelog...\n";
+
+chdir('..') || die "$progname: can't go back to ..: $!\n";
+if (-f $changelog) {
+ rename($changelog, "$changelog.bak") ||
+ die "$progname: can't rename $changelog into $changelog.bak: $!\n";
+}
+
+open(LOG, ">$changelog") || die "$progname: can't create $changelog: $!\n";
+&addlog("bugs/.xlog$bnum");
+if (-f "$changelog.bak") {
+ open(OLOG, "$changelog.bak") ||
+ die "$progname: can't open $changelog.bak: $!\n";
+ print LOG while <OLOG>;
+ close OLOG;
+}
+close LOG;
+
+print "$progname: checking in $changelog and computing diff...\n";
+
+# It is safe to run a patcil and a patdiff now, since the Changelog file has
+# been updated anyway: any log done while checking that file in will not
+# appear in the patch log nor the Changelog.
+
+system 'perl', '-S', 'patcil', '-p', $changelog;
+system 'perl', '-S', 'patdiff', $changelog;
+
+exit 0; # All done.
+
+# Returns true if .clog and .rlog (it it exists) are newer than .xlog.
+sub newertmp {
+ return 1 unless -f ".xlog$bnum"; # To force regeneration
+ return 1 if &newer(".clog$bnum", ".xlog$bnum") ||
+ (!$changercs || &newer(".rlog$bnum", ".xlog$bnum"));
+ 0;
+}
+
+# Returns true if $file is newer than the reference file $ref.
+sub newer {
+ local($file, $ref) = @_;
+ (stat($file))[9] >= (stat($ref))[9];
+}
+
+# Retursn true if $file is up-to-date with respect to .logs and .mods.
+sub uptodate {
+ local($file) = @_;
+ return 0 unless -f $file; # Cannot be up-to-date if missing
+ &newer($file, ".logs$bnum") && &newer($file, ".mods$bnum");
+}
+
+# Add file to the LOG descriptor, skipping the first three lines of that file.
+sub addlog {
+ local($file) = @_;
+ open(FILE, $file) || die "$progname: can't reopen $file: $!\n";
+ $_ = <FILE>; $_ = <FILE>; $_ = <FILE>;
+ print LOG while <FILE>;
+ close FILE;
+}
+
+# Build RCS logs, for each file listed in the %fileseen array, into %rcslog.
+# Common RCS log messages are grouped under the same entry.
+sub buildlogs {
+ local($log);
+ local(@files);
+ local($first);
+ local(%invertedlog);
+ foreach $file (keys %fileseen) {
+ $log = &rcslog($file);
+ next if $log eq '';
+ $invertedlog{$log} .= "$file ";
+ }
+ foreach $log (keys %invertedlog) {
+ @files = split(' ', $invertedlog{$log});
+ $first = (sort @files)[0];
+ $rcslog{$first} = join(', ', @files) . ': ' . $log;
+ }
+}
+
+# Grab log for a given file by parsing its $Log section. Only comments
+# relevant to the patch are kept. This relies on the presence of the patchxx:
+# leading string in front of each comment.
+# If not sufficient (because people don't use patchxx prefixes), then we'll
+# need a more sophisticated algorithm parsing revisions lines to see where we
+# left of at the last patch.
+sub rcslog {
+ local($file) = @_;
+ open(FILE, "../$file") || warn "$me: can't open $file: $!\n";
+ local($_);
+ local($comment, $len);
+ local($pcomment) = "patch$bnum:";
+ local($plen) = length($pcomment);
+ local($c);
+ local($lastnl) = 1;
+ local($kept); # Relevant part of the RCS comment which is kept
+ file: while (<FILE>) {
+ if (/^(.*)\$Log[:\$]/) {
+ $comment = $1;
+ $comment =~ s/\s+$//; # Newer RCS chop spaces on emtpy lines
+ $len = length($comment);
+ while (<FILE>) {
+ $c = substr($_, 0, $len);
+ last file unless $c eq $comment;
+ $_ = substr($_, $len, 9_999);
+ if ($lastnl) {
+ last file unless /^\s*Revision\s+\d/;
+ $lastnl = 0;
+ } elsif (/^\s*$/) {
+ $lastnl = 1;
+ } else {
+ s/^\s*//; # Older RCS will have space here
+ $c = substr($_, 0, $plen);
+ last file unless $c eq $pcomment;
+ # Comment for that patch is kept after space cleanup
+ $_ = substr($_, $plen, 9_999);
+ s/^\s*//;
+ s/\s*$//;
+ $_ .= '.' unless /\.$/;
+ s/^(.)/\U$1/; # Ensure upper-cased to start sentence
+ s/^/ / if $kept;
+ $kept .= $_; # Will be reformatted later on
+ }
+ }
+ }
+ }
+ close FILE;
+ $kept;
+}
+
+# Format line to fit in 80 columns (70 + 8 for the added leading tabs).
+# Rudimentary parsing to break lines after a , or a space.
+sub format {
+ local($_) = @_;
+ local($tmp);
+ local($msg);
+ while (length($_) > 70) {
+ $tmp = substr($_, 0, 70);
+ $tmp =~ s/^(.*)([,\s]).*/$1/;
+ $msg .= "\t$tmp" . ($2 eq ',' ? ',' : '') . "\n";
+ $_ = substr($_, length($tmp), 9_999);
+ $_ =~ s/^\s+//;
+ }
+ $msg .= "\t$_\n";
+ $msg;
+}
+
+sub usage {
+ print STDERR <<EOM;
+Usage: $progname [-hnruV]
+ -h : print this message and exit.
+ -n : not-really mode: force re-edit, but stop after updating.
+ -r : reuse existing change file candidate entries (supersedes -u).
+ -u : update mode, recreate files only when out of date.
+ -V : print version number and exit.
+EOM
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/package.pl >>patlog
+$grep -v '^;#' ../pl/tilde.pl >>patlog
+$grep -v '^;#' ../pl/profile.pl >>patlog
+chmod +x patlog
+$eunicefix patlog
diff --git a/pat/patmake.SH b/pat/patmake.SH
new file mode 100644
index 0000000..c85f729
--- /dev/null
+++ b/pat/patmake.SH
@@ -0,0 +1,413 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patmake (with variable substitutions)"
+cat >patmake <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patmake.SH,v 3.0.1.5 1995/09/25 09:21:19 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# Original Author: Larry Wall <lwall@netlabs.com>
+# Contribution by: Graham Stoney <greyham@research.canon.oz.au>
+#
+# $Log: patmake.SH,v $
+# Revision 3.0.1.5 1995/09/25 09:21:19 ram
+# patch59: now calls patsend with -i to add more instructions
+#
+# Revision 3.0.1.4 1994/10/29 16:43:09 ram
+# patch36: a lot of setup is now performed by patlog
+# patch36: added various escapes in strings for perl5 support
+#
+# Revision 3.0.1.3 1994/01/24 14:30:55 ram
+# patch16: now prefix error messages with program's name
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.2 1993/08/24 12:18:59 ram
+# patch3: now asks for patch mailing/posting after all patches edited
+# patch3: patch release notification is done via new patnotify
+# patch3: random cleanup, removed old RCS logs
+#
+# Revision 3.0.1.1 1993/08/19 06:42:38 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:45 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+\$defeditor='$defeditor';
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+\$mailer = '$mailer';
+!GROK!THIS!
+cat >>patmake <<'!NO!SUBS!'
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless &Getopts("hV");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+&readpackage;
+&readusers;
+
+$FILEOVERHEAD = 40; # Name of files, Index, Prereq
+$MAXPATSIZE = 50000; # Maximum allowed size for a patch
+$PATOVERHEAD = 2500; # Litterature
+$FIRST_PAT = 3000; # Give space for first patch (descriptions)
+
+if (-f 'patchlevel.h') {
+ open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n";
+ while (<PL>) {
+ if (/^#define\s+PATCHLEVEL\s+(\d+)/) {
+ $last = $1;
+ $patchline = $.; # Record PATCHLEVEL line
+ }
+ }
+ die "$progname: malformed patchlevel.h file.\n" if $last eq '';
+ $bnum = $last + 1;
+}
+else {
+ $patchline = 1;
+ $bnum = 1;
+ $last = '';
+}
+
+@ARGV = <[Mm]akefile*>;
+$mf = '';
+if ($#ARGV > 0) {
+ while (<>) {
+ $mf .= $_ if /^[a-z.]+\s*:/; # Rules in makefile
+ }
+}
+$* = 1;
+$after = '';
+$after .= "\t\tConfigure -ders\n" if -f 'Configure';
+$after .= "\t\tmake depend\n" if $mf =~ /^depend:/;
+$after .= "\t\tmake\n" if $mf;
+$after .= "\t\tmake test\n" if $mf =~ /^test:/;
+$after .= "\t\tmake install\n" if $mf =~ /^install:/;
+$after .= "\t\tmake install.man\n" if $mf =~ /^install\.man:/;
+$* = 0;
+
+chdir 'bugs' if -d 'bugs';
+die "$progname: patch #$bnum already exists.\n" if -f "patch$bnum";
+
+@patlist=<*.$bnum>;
+die "$progname: no diff files for patch #$bnum.\n" if
+ $patlist[0] =~ /^\*/ || $patlist[0] eq '';
+
+# Whether they asked for a changelog file or not, call patlog.
+# This will create at least the .pri and .subj and .clog files that we need.
+# If a changelog file is needed, it will update it and create the necessary
+# patch before we go on and put all those patches together.
+# Note that we make use of the '-r' option, in case they have already
+# run patlog themselves and made the necessary adjustments. Since -r supersedes
+# -u, it's safe to allow ~/.dist_profile processing anyway.
+
+chdir '..' if -d '../bugs';
+system 'perl', '-S', 'patlog', '-r'; # Must be called from top-level dir
+chdir 'bugs' if -d 'bugs';
+
+@patlist=<*.$bnum>; # Reget it, in case Changes.xx appeared due to patlog
+
+# Look for size of each diff file
+for (@patlist) {
+ ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,
+ $blksize,$blocks) = stat($_);
+ $size{$_} = $size;
+}
+
+# Sort the array, biggest sizes first
+sub revnum { $size{$a} < $size{$b} ? 1 : $size{$a} > $size{$b} ? -1 : 0; }
+@patlist = sort revnum @patlist;
+
+# Put files in a patch
+for (@patlist) {
+ $i=1;
+ # Find the patch in which the current file can go
+ # Divide size by 15 to count the 3 spaces added in front of each line
+ while (($newtot = int($tot[$i] + $size{$_} + $size{$_}/15 + $FILEOVERHEAD)) >
+ $MAXPATSIZE-$PATOVERHEAD-($i == 1 ? $FIRST_PAT : 0) && $tot[$i]) {
+ $i++;
+ }
+ # Adding $_ to patch $i giving $newtot bytes
+ $tot[$i] = $newtot; # Update size of kit $i
+ $list[$i] .= " $_"; # Add file to the kit $i
+}
+
+$numpat = $#list; # Number of patches to generate
+
+if ($numpat > 1) {
+ print "$progname: Warning: generating $numpat patches.\n";
+ sleep(1);
+}
+
+$hah = " (hah!)" if $bnum == 1;
+$patbase = $bnum; # First patch generated
+
+open(PRIORITY, ".pri$bnum");
+chop($priority = <PRIORITY>);
+close PRIORITY;
+$priority = 'LOW' unless $priority;
+
+for ($i = 1; $i <= $numpat; $i++) { # For all patches...
+ open(PATCH,">patch$bnum") || die "Can't create patch #$bnum";
+ chop($date=`date`);
+ print PATCH
+"System: $package version $baserev
+Patch #: $bnum
+";
+ print PATCH "Priority: $priority\n" unless $priority eq '';
+ # Print subjects only for first patch
+ if ($i == 1) {
+ open(SUBJECTS, ".subj$bnum");
+ print PATCH while <SUBJECTS>;
+ close SUBJECTS;
+ } else {
+ print PATCH "Subject: patch #$patbase, continued\n";
+ }
+ print PATCH
+"Date: $date
+From: $maintname <$maintloc>
+
+Description:
+";
+ # Print description and repeat-by only for first patch
+ if ($i == 1) {
+ open(LOGS, ".clog$bnum");
+ $_ = <LOGS>; $_ = <LOGS>; $_ = <LOGS>; # Skip first three lines
+ print PATCH while <LOGS>;
+ close LOGS;
+ print PATCH "Repeat-By: \n";
+ } else {
+ print PATCH "\tSee patch #$patbase.\n\n";
+ }
+ print PATCH
+"
+Fix: From rn, say \"| patch -p -N -d DIR\", where DIR is your $package source
+ directory. Outside of rn, say \"cd DIR; patch -p -N <thisarticle\".
+ If you don't have the patch program, apply the following by hand,
+ or get patch (version 2.0, latest patchlevel).
+
+ After patching:
+";
+ # Do $after only after last patch
+ if ($i == $numpat) {
+ print PATCH $after;
+ } else {
+ printf PATCH
+"\t\t*** DO NOTHING--INSTALL ALL PATCHES UP THROUGH #%d FIRST ***\n",
+$patbase + $numpat - 1;
+ }
+ print PATCH "
+ If patch indicates that patchlevel is the wrong version, you may need
+ to apply one or more previous patches, or the patch may already
+ have been applied. See the patchlevel.h file to find out what has or
+ has not been applied. In any event, don't continue with the patch.
+
+ If you are missing previous patches$hah they can be obtained from me:
+
+ $maintname <$maintloc>
+
+";
+ if ($mailagent ne 'false') {
+ print PATCH
+" If you send a mail message of the following form it will greatly speed
+ processing:
+
+ Subject: Command
+ \@SH mailpatch PATH $package $baserev LIST
+ ^ note the c
+
+ where PATH is a return path FROM ME TO YOU either in Internet notation,
+ or in bang notation from some well-known host, and LIST is the number
+ of one or more patches you need, separated by spaces, commas, and/or
+ hyphens. Saying 35- says everything from 35 to the end.
+
+ To get some more detailed instructions, send me the following mail:
+
+ Subject: Command
+ \@SH mailhelp PATH
+
+";
+ }
+ if ($ftpsite) {
+ print PATCH
+" You can also get the patches via anonymous FTP from
+ $ftpsite.
+";
+ }
+ # Print patchlevel at the top of each patch
+ print PATCH "
+Index: patchlevel.h
+";
+ if ($last eq '') {
+ `echo "#define PATCHLEVEL 1" >patchlevel.h`;
+ `cp /dev/null patchlevel.h.null`;
+ print PATCH `diff -c patchlevel.h.null patchlevel.h`;
+ unlink 'patchlevel.h', 'patchlevel.h.null';
+ }
+ else {
+ print PATCH
+"Prereq: $last
+${patchline}c${patchline}
+< #define PATCHLEVEL $last
+---
+> #define PATCHLEVEL $bnum
+";
+ }
+ $last = $bnum; # Update last patch
+ push(@patset, $bnum); # Record set of generated patch(es)
+
+ @ARGV = split(' ', $list[$i]);
+ while (<>) { print PATCH; }
+ print PATCH "\n*** End of Patch $bnum ***\n";
+ close PATCH;
+
+ # Update patchlevel.h file
+ $editor = $ENV{'VISUAL'};
+ $editor = $ENV{'EDITOR'} unless $editor;
+ $editor = $defeditor unless $editor;
+ $editor = 'vi' unless $editor;
+ system $editor, "patch$bnum";
+ if (-s "patch$bnum") {
+ system 'chmod', '-w', "patch$bnum"; # Protect newly created patch
+ chdir '..';
+ `echo "#define PATCHLEVEL 0" >patchlevel.h` unless -f 'patchlevel.h';
+ open(PL,"patchlevel.h") ||
+ die "$progname: can't open patchlevel.h: $!\n";
+ open(PLN,">patchlevel.h+") ||
+ die "$progname: can't create new patchlevel.h: $!\n";
+ while (<PL>) {
+ if (/^#define\s+PATCHLEVEL\s+(\d+)/) {
+ $bnum = $1;
+ $bnum++; # Update patch level
+ print PLN "#define PATCHLEVEL $bnum\n";
+ } else {
+ print PLN; # Simply copy other lines
+ }
+ }
+ close PLN;
+ close PL;
+ `mv -f patchlevel.h+ patchlevel.h`;
+ die "$progname: malformed patchlevel.h file.\n" if $bnum eq '';
+ } else {
+ unlink "patch$bnum";
+ die "$progname: aborted.\n";
+ }
+
+ chdir 'bugs' || die "$progname: cannot cd to bugs: $!\n";
+
+ # Find priority for next patch in loop
+ $priority='';
+ open(PATCH, "patch$bnum") || die "Cannot re-open patch #$bnum !\n";
+ while (<PATCH>) {
+ /^Priority:\s*(\S+)\s*$/ && ($priority = $1);
+ }
+ close PATCH;
+
+ $bnum++; # For next patch in loop
+}
+
+utime time, time, 'patchlevel.h'; # Reset timestamp on patchlevel
+
+if (@patset == 1) {
+ $bnum = pop(@patset);
+ $patch = "patch #$bnum";
+} else {
+ $bmin = shift(@patset);
+ $bmax = pop(@patset);
+ $bnum = "$bmin-$bmax";
+ $patch = "patches #$bmin thru #$bmax";
+}
+
+# Post generated patches
+if ($newsgroups) {
+ print "\nDo you wish to post $patch to $newsgroups? [y] ";
+ $ans = <stdin>;
+ system 'patpost', $bnum unless $ans =~ /^n/i;
+}
+
+# Mail generated patches
+if ($recipients) {
+ print "\n";
+ if (0 == ($recipients =~ tr/ //)) {
+ print "Do you wish to send $patch to $recipients? [y] ";
+ } else {
+ print "The following people are on the recipient list:\n\n";
+ foreach $addr (split(' ', $recipients)) {
+ print "\t$addr\n";
+ }
+ print "\nDo you wish to send $patch to them? [y] ";
+ }
+ $ans = <stdin>;
+ system 'patsend', '-i', $bnum, $recipients unless $ans =~ /^n/i;
+}
+
+# Copy patches to FTP directory
+if ($ftpdir) {
+ print "\nDo you wish to copy $patch to $ftpdir? [y] ";
+ $ans = <stdin>;
+ system 'patftp', $bnum unless $ans =~ /^n/i;
+}
+
+# Notify people about it.
+if ($notify) {
+ print "\n";
+ if (0 == ($notify =~ tr/ //)) {
+ print "Do you wish to notify $notify? [y] ";
+ } else {
+ print "The following people are on the notify list:\n\n";
+ foreach $addr (split(' ', $notify)) {
+ print "\t$addr\n";
+ }
+ print "\nDo you wish to notify them? [y] ";
+ }
+ $ans = <STDIN>;
+ system 'patnotify', $notify unless $ans =~ /^n/i;
+}
+
+sub usage {
+ print STDERR <<EOM;
+Usage: $progname [-hV]
+ -h : print this message and exit
+ -V : print version number and exit
+EOM
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/package.pl >>patmake
+$grep -v '^;#' ../pl/users.pl >>patmake
+$grep -v '^;#' ../pl/tilde.pl >>patmake
+$grep -v '^;#' ../pl/profile.pl >>patmake
+chmod +x patmake
+$eunicefix patmake
diff --git a/pat/patname.SH b/pat/patname.SH
new file mode 100644
index 0000000..c22696d
--- /dev/null
+++ b/pat/patname.SH
@@ -0,0 +1,175 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patname (with variable substitutions)"
+cat >patname <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patname.SH,v 3.0.1.2 1994/01/24 14:31:02 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# $Log: patname.SH,v $
+# Revision 3.0.1.2 1994/01/24 14:31:02 ram
+# patch16: now prefix error messages with program's name
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.1 1993/08/19 06:42:40 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:46 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+cat >>patname <<'!NO!SUBS!'
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless $#ARGV >= 0;
+&usage() unless &Getopts("ahnmv:V");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+$RCSEXT = ',v' unless $RCSEXT;
+$ENV{'DIST'} = '/dev/null'; # Disable ~/.dist_profile
+
+chop($pwd = `pwd`) unless -f '.package';
+until (-f '.package') {
+ die "$progname: no .package file! Run packinit.\n" unless $pwd;
+ chdir '..' || die "$progname: can't cd ..: $!\n";
+ $pwd =~ s|(.*)/(.*)|$1|;
+ $prefix = $2 . '/' . $prefix;
+}
+if ($prefix) {
+ for (@ARGV) {
+ s/^/$prefix/ unless m|^[-/]|;
+ }
+}
+
+# We now are at the top level
+
+&readpackage;
+
+unless ($opt_v) {
+ print STDERR "$progname: version number must be specified using -v.\n";
+ &usage;
+}
+
+if ($opt_n) {
+ &newer; # Look for files newer than patchlevel.h
+} elsif ($opt_a) {
+ open(MANI,"MANIFEST.new") || die "$progname: can't read MANIFEST.new: $!\n";
+ @ARGV = ();
+ while (<MANI>) {
+ s|^\./||;
+ next if m|^patchlevel.h|; # This file is built by hand
+ chop;
+ ($_) = split(' ');
+ next if -d;
+ push(@ARGV,$_);
+ }
+ close MANI;
+} elsif ($opt_m) {
+ open(MODS,"bugs/.mods$bnum") || die "$progname: no modification found.\n";
+ @ARGV = ();
+ while (<MODS>) {
+ next if m|^patchlevel.h$|; # This file is built by hand
+ chop;
+ ($_) = split(' ');
+ push(@ARGV,$_);
+ }
+ close MODS;
+}
+
+# Now loop over each file specified, doing a 'rcsfreeze'
+foreach $file (@ARGV) {
+ $files = &rcsargs($file);
+ @files = split(' ', $files);
+ $rlog = `rlog -rlastpat- $files 2>&1`;
+ ($revs) = ($rlog =~ /selected revisions: (\d+)/);
+ if (!$revs) {
+ print "$progname: $file has never been checked in--checking in...\n";
+ system 'perl', '-S', 'patcil', '-p', $file;
+ $revs = 2; # At least null trunk + new fresh revision
+ }
+ # Look whether there is a branch
+ if ($revs == 1) {
+ $rlog = `rlog -r$revbranch $files 2>&1`;
+ ($revs) = ($rlog =~ /selected revisions: (\d+)/);
+ $revs++; # add the base revision
+ }
+ # If working file exists, make sure latest version was checked in
+ if (-f $file) {
+ if ($revs == 1) {
+ $delta = `rcsdiff -r$baserev $files 2>/dev/null`;
+ } else {
+ $delta = `rcsdiff -r$revbranch $files 2>/dev/null`;
+ }
+ if ($delta ne '') {
+ # File changed; check it in.
+ system 'perl', '-S', 'patcil', '-p', $file;
+ if ($revs > 1) {
+ # Have to re-run rlog after a new ci
+ $rlog = `rlog -r$revbranch $files 2>&1`;
+ }
+ }
+ }
+ # Now assign symbolic revision number
+ if ($revs == 1) {
+ system 'rcs', "-N$opt_v:$baserev", @files;
+ } else {
+ ($lastrev) = ($rlog =~ /revision $revbranch\.(\d+)/);
+ system 'rcs', "-N$opt_v:$revbranch.$lastrev", @files;
+ }
+}
+
+sub usage {
+ print STDERR <<EOM;
+Usage: $progname [-ahnmV] -v version [filelist]
+ -a : all the files in MANIFEST.new
+ -h : print this message and exit
+ -n : all the files newer than patchlevel.h
+ -m : all the modified files (which have been patciled)
+ -v : set version number (mandatory)
+ -V : print version number and exit
+EOM
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/newer.pl >>patname
+$grep -v '^;#' ../pl/package.pl >>patname
+$grep -v '^;#' ../pl/rcsargs.pl >>patname
+$grep -v '^;#' ../pl/tilde.pl >>patname
+$grep -v '^;#' ../pl/profile.pl >>patname
+chmod +x patname
+$eunicefix patname
diff --git a/pat/patnotify.SH b/pat/patnotify.SH
new file mode 100644
index 0000000..7fc27e9
--- /dev/null
+++ b/pat/patnotify.SH
@@ -0,0 +1,232 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patnotify (with variable substitutions)"
+cat >patnotify <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patnotify.SH,v 3.0.1.9 1997/02/28 16:33:35 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# $Log: patnotify.SH,v $
+# Revision 3.0.1.9 1997/02/28 16:33:35 ram
+# patch61: let them know the patch priority and description
+#
+# Revision 3.0.1.8 1995/09/25 09:21:43 ram
+# patch59: now tells users how to directly request for mailed patches
+#
+# Revision 3.0.1.7 1994/10/29 16:43:19 ram
+# patch36: added various escapes in strings for perl5 support
+#
+# Revision 3.0.1.6 1994/06/20 07:11:47 ram
+# patch30: patnotify now includes the e-mail address for requests
+#
+# Revision 3.0.1.5 1994/01/24 14:31:48 ram
+# patch16: now prefix error messages with program's name
+# patch16: don't feed mailer with more than 50 addresses at a time
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.4 1993/08/27 14:40:42 ram
+# patch7: two files were wrongly appended to patsend instead
+#
+# Revision 3.0.1.3 1993/08/25 14:07:43 ram
+# patch6: now asks for recipient list edition by default
+# patch6: new -q option to suppress that
+#
+# Revision 3.0.1.2 1993/08/24 12:48:03 ram
+# patch5: fixed fatal typo in here document
+#
+# Revision 3.0.1.1 1993/08/24 12:19:11 ram
+# patch3: created
+#
+
+\$defeditor='$defeditor';
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+\$mailer = '$mailer';
+!GROK!THIS!
+cat >>patnotify <<'!NO!SUBS!'
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless &Getopts("hquV");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+chdir '..' if -d '../bugs';
+
+&readpackage;
+&readusers if $opt_u;
+
+$dest = join(' ', @ARGV);
+$dest .= " $notify" if $opt_u;
+
+&usage unless $dest;
+
+# Offer to edit the address list unless -q
+unless ($opt_q) {
+ select((select(STDOUT), $| = 1)[0]);
+ print "Do you wish to edit the address list? [y] ";
+ $ans = <STDIN>;
+ unless ($ans =~ /^n/i) {
+ @to = split(' ', $dest);
+ &listedit(*to);
+ $dest = join(' ', @to);
+ }
+}
+
+if (-f 'patchlevel.h') {
+ open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n";
+ while (<PL>) {
+ if (/^#define\s+PATCHLEVEL\s+(\d+)/) {
+ $last = $1;
+ }
+ }
+ die "$progname: malformed patchlevel.h file.\n" if $last eq '';
+} else {
+ die "$progname: no patchlevel.h.\n";
+}
+
+@patches = &patseq($last); # Compute patches sequence
+$lastpat = pop(@patches);
+
+warn "$progname: missing last .logs and .mods files\n" if $lastpat eq '';
+
+$missing = $last - $lastpat + 1;
+$these = $missing == 1 ? 'this' : 'these';
+$patches = $missing == 1 ? 'patch' : 'patches';
+$through = $missing == 1 ? $lastpat : "$lastpat thru " . ($lastpat+$missing-1);
+$have = $missing == 1 ? 'has' : 'have';
+$patlist = "$lastpat-"; # They'll get everything up to the end
+
+($Patches = $patches) =~ s/^p/P/;
+$opt = ($mailer =~ /sendmail/) ? '-odq' : '';
+
+chdir 'bugs' || die "$progname: can't cd to bugs: $!\n";
+
+# Find out priority of last patch set
+$priority = 'UNKNOWN';
+open(PATCH, "patch$lastpat") ||
+ die "$progname: can't open patch #$lastpat: $!\n";
+while (<PATCH>) {
+ /^Priority:\s*(\S+)\s*$/ && ($priority = $1);
+}
+close PATCH;
+
+# Look for the .clog<patch #> description and prepare the patch description
+# for inclusion in the notification, so that they can figure out whether
+# they really need that patch set.
+
+if (-f ".clog$lastpat") {
+ open(LOGS, ".clog$lastpat") ||
+ die "$progname: can't open .clog$lastpat: $!\n";
+ $_ = <LOGS> . <LOGS> . <LOGS>; # Skip first three lines
+ $clog = '';
+ while (<LOGS>) {
+ $clog .= $_;
+ }
+ close LOGS;
+} else {
+ warn "$progname: missing last .clog file in bugs directory\n";
+}
+
+print "$progname: sending notification of $missing new $patches to $dest...\n";
+
+fork && exit;
+
+# I hate broken mailers! Bust it up into smaller groups of people...
+@dest = split(' ', $dest);
+while (@smalldest = splice(@dest, 0, 50)) {
+ $to = join(', ', @smalldest); # Sensible To: for sendmail
+ $smalldest = join(' ', @smalldest);
+
+ open(MAILER, "|$mailer $opt $smalldest") ||
+ die "$progname: can't fork $mailer: $!\n";
+ print MAILER
+"To: $to
+Subject: $Patches $through for $package version $baserev $have been released.
+Precedence: bulk
+X-Mailer: dist [version $version PL$patchlevel]
+
+This is just a quick note to let you know that $package version $baserev
+has been recently upgraded and that $patches $through $have been released.
+
+If you are actively using $package, I strongly suggest you upgrade by
+applying $these $patches, whose priority is $priority.
+
+You can fetch $these $patches automatically by sending me the following mail:
+
+ Subject: Command
+ \@SH mailpatch - $package $baserev $patlist
+ ^ note the c
+
+And if you wish to have future patches mailed directly to you, you can add:
+
+ \@SH package - $package $baserev - mailpatches
+
+If you are not interested in receiving any information about future patches,
+please send me the following mail:
+
+ Subject: Command
+ \@SH package - $package $baserev
+";
+ print MAILER
+"
+Following is the $patches description:
+
+$clog" if $clog;
+ print MAILER
+"
+-- $progname speaking for $maintname <$maintloc>.
+";
+ close MAILER;
+}
+
+sub usage {
+ print STDERR <<EOH;
+Usage: $progname [-hquV] [recipients]
+ -h : print this message and exit
+ -q : quick mode, do not offer to edit recipient list
+ -u : add all to-be-notified users
+ -V : print version number and exit
+EOH
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/package.pl >>patnotify
+$grep -v '^;#' ../pl/users.pl >>patnotify
+$grep -v '^;#' ../pl/patseq.pl >>patnotify
+$grep -v '^;#' ../pl/editor.pl >>patnotify
+$grep -v '^;#' ../pl/listedit.pl >>patnotify
+$grep -v '^;#' ../pl/tilde.pl >>patnotify
+$grep -v '^;#' ../pl/profile.pl >>patnotify
+chmod +x patnotify
+$eunicefix patnotify
diff --git a/pat/patpost.SH b/pat/patpost.SH
new file mode 100644
index 0000000..8f245bd
--- /dev/null
+++ b/pat/patpost.SH
@@ -0,0 +1,179 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patpost (with variable substitutions)"
+cat >patpost <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patpost.SH,v 3.0.1.4 1995/05/12 12:25:58 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# Original Author: Larry Wall <lwall@netlabs.com>
+#
+# $Log: patpost.SH,v $
+# Revision 3.0.1.4 1995/05/12 12:25:58 ram
+# patch54: added explicit From: header line pointing to the maintainer
+#
+# Revision 3.0.1.3 1994/01/24 14:32:09 ram
+# patch16: now prefix error messages with program's name
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.2 1993/08/24 12:19:48 ram
+# patch3: added ~name expansion for orgname
+# patch3: random cleanup
+#
+# Revision 3.0.1.1 1993/08/19 06:42:41 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:47 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+\$inews='${inews-/usr/lib/news/inews}';
+\$orgname='$orgname';
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+
+cat >>patpost <<'!NO!SUBS!'
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless $#ARGV >= 0;
+&usage unless &Getopts("hrV");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+$RCSEXT = ',v' unless $RCSEXT;
+if ($inews eq 'inews') {
+ $inews = '/usr/lib/news/inews' if -f '/usr/lib/news/inews';
+}
+
+chdir '..' if -d '../bugs';
+
+&readpackage;
+
+$orgname = &tilda_expand($orgname);
+chop($orgname = `cat $orgname`) if $orgname =~ m|^/|;
+
+if ($opt_r) {
+ $repost = ' (REPOST)';
+}
+
+while ($_ = shift) {
+ if (/^(patch)?[1-9][\d\-]*$/) {
+ s/^patch//;
+ push(@argv,$_);
+ } else {
+ push(@newsgroups,$_);
+ }
+}
+$newsgroups = join(',',@newsgroups) unless $#newsgroups < 0;
+&usage unless $newsgroups;
+
+@ARGV = @argv;
+open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n";
+while (<PL>) {
+ $maxnum = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/;
+}
+close PL;
+die "$progname: malformed patchlevel.h file.\n" if $maxnum eq '';
+
+if ($#ARGV < 0) {
+ @patseq = &patseq($maxnum);
+ $lastpat = pop(@patseq);
+ $argv = &rangeargs("$lastpat-$maxnum");
+}
+else {
+ $argv = &rangeargs(@ARGV);
+}
+
+@ARGV = split(' ',$argv);
+$argv =~ s/ $//;
+
+if ($#ARGV < 0) {
+ print STDERR "$progname: no patches specified.\n";
+ &usage;
+} elsif ($#ARGV) {
+ print
+ "$progname: posting $package $baserev patches $argv to $newsgroups...\n";
+} else {
+ print
+ "$progname: posting $package $baserev patch $argv to $newsgroups...\n";
+}
+
+chdir 'bugs' || die "$progname: can't cd to bugs: $!\n";
+
+fork && exit;
+
+until ($#ARGV < 0) {
+ $patnum = shift;
+ open(PATCH,"patch$patnum") ||
+ die "$progname: can't open patch$patnum: $!\n";
+ open(XHEAD,"|$inews -h") || die "$progname: can't fork $inews: $!\n";
+ print XHEAD
+"From: $maintloc ($maintname)
+Newsgroups: $newsgroups
+Subject: $package $baserev patch #$patnum$repost
+Summary: This is an official patch for $package $baserev. Please apply it.
+Expires:
+References:
+Sender:
+Distribution:
+Organization: $orgname
+Keywords:
+
+";
+ while (<PATCH>) {
+ print XHEAD;
+ }
+ close PATCH;
+ close XHEAD;
+ die "$progname: could not post patch$patnum.\n" if $?;
+}
+
+sub usage {
+ print STDERR <<EOM;
+Usage: $progname [-hrV] patchlist newsgroups
+ -h : print this message and exit
+ -r : signals a repost
+ -V : print version number and exit
+EOM
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/package.pl >>patpost
+$grep -v '^;#' ../pl/rangeargs.pl >>patpost
+$grep -v '^;#' ../pl/patseq.pl >>patpost
+$grep -v '^;#' ../pl/tilde.pl >>patpost
+$grep -v '^;#' ../pl/profile.pl >>patpost
+chmod +x patpost
+$eunicefix patpost
diff --git a/pat/patsend.SH b/pat/patsend.SH
new file mode 100644
index 0000000..6a5b4aa
--- /dev/null
+++ b/pat/patsend.SH
@@ -0,0 +1,218 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patsend (with variable substitutions)"
+cat >patsend <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patsend.SH,v 3.0.1.6 1995/09/25 09:22:02 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# Original Author: Larry Wall <lwall@netlabs.com>
+#
+# $Log: patsend.SH,v $
+# Revision 3.0.1.6 1995/09/25 09:22:02 ram
+# patch59: new -i option to add more instructions for end-users
+#
+# Revision 3.0.1.5 1994/01/24 14:32:46 ram
+# patch16: now prefix error messages with program's name
+# patch16: don't feed mailer with more than 50 addresses at a time
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.4 1993/08/25 14:08:01 ram
+# patch6: now asks for recipient list edition by default
+# patch6: new -q option to suppress that
+#
+# Revision 3.0.1.3 1993/08/24 12:21:59 ram
+# patch3: new -u option
+# patch3: added Precedence and X-Mailer headers in mail message
+# patch3: added ~name expansion for orgname
+#
+# Revision 3.0.1.2 1993/08/19 07:10:19 ram
+# patch3: was not correctly writing the To: header field
+#
+# Revision 3.0.1.1 1993/08/19 06:42:42 ram
+# patch1: leading config.sh searching was not aborting properly
+#
+# Revision 3.0 1993/08/18 12:10:49 ram
+# Baseline for dist 3.0 netwide release.
+#
+
+\$orgname='$orgname';
+\$mailer='$mailer';
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+cat >>patsend <<'!NO!SUBS!'
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless &Getopts("hiquV");
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+chdir '..' if -d '../bugs';
+
+&readpackage;
+&readusers if $opt_u;
+
+$orgname = &tilda_expand($orgname);
+chop($orgname = `cat $orgname`) if $orgname =~ m|^/|;
+
+while ($_ = shift) {
+ if (/^(patch)?[1-9][\d,-]*$/) {
+ s/^patch//;
+ push(@argv,$_);
+ } else {
+ push(@dest,$_);
+ }
+}
+$dest = join(' ',@dest);
+$dest .= " $recipients" if $opt_u;
+&usage unless $dest;
+
+# Offer to edit the address list unless -q
+unless ($opt_q) {
+ select((select(STDOUT), $| = 1)[0]);
+ print "Do you wish to edit the address list? [y] ";
+ $ans = <STDIN>;
+ unless ($ans =~ /^n/i) {
+ @to = split(' ', $dest);
+ &listedit(*to);
+ $dest = join(' ', @to);
+ }
+}
+
+$to = join(', ', split(' ', $dest));
+@ARGV = @argv;
+
+open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n";
+while (<PL>) {
+ $maxnum = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/;
+}
+close PL;
+die "$progname: malformed patchlevel.h file.\n" if $maxnum eq '';
+
+if ($#ARGV < 0) {
+ @patseq = &patseq($maxnum);
+ $lastpat = pop(@patseq);
+ $argv = &rangeargs("$lastpat-$maxnum");
+} else {
+ $argv = &rangeargs(@ARGV);
+}
+
+@ARGV = split(' ',$argv);
+$argv =~ s/ $//;
+
+if ($#ARGV < 0) {
+ print STDERR "$progname: no patches specified.\n";
+ &usage;
+} elsif ($#ARGV) {
+ print "$progname: sending $package $baserev patches $argv to $dest...\n";
+} else {
+ print "$progname: sending $package $baserev patch $argv to $dest...\n";
+}
+
+chdir 'bugs' || die "$progname: can't cd to bugs: $!\n";
+
+fork && exit;
+
+$opt = '-odq' if $mailer =~ /sendmail/;
+
+until ($#ARGV < 0) {
+ $patnum = shift;
+
+ # I hate broken mailers! Bust it up into smaller groups of people...
+ @dest = split(' ', $dest);
+ while (@smalldest = splice(@dest, 0, 50)) {
+ $to = join(', ', @smalldest); # Sensible To: for sendmail
+ $smalldest = join(' ', @smalldest);
+
+ open(MAILER, "|$mailer $opt $smalldest") ||
+ die "$progname: can't fork $mailer: $!\n";
+ print MAILER
+"To: $to
+Subject: $package $baserev patch #$patnum
+Precedence: bulk
+X-Mailer: dist [version $version PL$patchlevel]
+Organization: $orgname
+
+";
+ print MAILER
+"$package version $baserev has been recently upgraded with the following patch,
+which is being mailed directly to you as you requested when running Configure.
+
+If you are not interested in having future patches mailed directly to you,
+please send me the following mail:
+
+ Subject: Command
+ \@SH package - $package $baserev
+
+-- $progname speaking for $maintname <$maintloc>.
+
+" if ($opt_i || $opt_u);
+ print MAILER
+"[The latest patch for $package version $baserev is #$maxnum.]
+
+";
+ open(PATCH,"patch$patnum") ||
+ die "$progname: can't open patch$patnum: $!\n";
+ while (<PATCH>) {
+ print MAILER;
+ }
+ close PATCH;
+ close MAILER;
+ die "$progname: could not mail patch$patnum.\n" if $?;
+ }
+}
+
+sub usage {
+ print STDERR <<EOM;
+Usage: $progname [-hiquV] [patchlist] [recipients]
+ -h : print this message and exit
+ -i : include information on how to stop receiving future patches
+ -q : quick mode, do not offer to edit recipient list
+ -u : add all to-be-mailed users
+ -V : print version number and exit
+EOM
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/package.pl >>patsend
+$grep -v '^;#' ../pl/rangeargs.pl >>patsend
+$grep -v '^;#' ../pl/users.pl >>patsend
+$grep -v '^;#' ../pl/patseq.pl >>patsend
+$grep -v '^;#' ../pl/tilde.pl >>patsend
+$grep -v '^;#' ../pl/editor.pl >>patsend
+$grep -v '^;#' ../pl/listedit.pl >>patsend
+$grep -v '^;#' ../pl/profile.pl >>patsend
+chmod +x patsend
+$eunicefix patsend
diff --git a/pat/patsnap.SH b/pat/patsnap.SH
new file mode 100644
index 0000000..87274b8
--- /dev/null
+++ b/pat/patsnap.SH
@@ -0,0 +1,124 @@
+case $CONFIG in
+'')
+ if test -f config.sh; then TOP=.;
+ elif test -f ../config.sh; then TOP=..;
+ elif test -f ../../config.sh; then TOP=../..;
+ elif test -f ../../../config.sh; then TOP=../../..;
+ elif test -f ../../../../config.sh; then TOP=../../../..;
+ else
+ echo "Can't find config.sh."; exit 1
+ fi
+ . $TOP/config.sh
+ ;;
+esac
+case "$0" in
+*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
+esac
+echo "Extracting pat/patsnap (with variable substitutions)"
+cat >patsnap <<!GROK!THIS!
+$startperl
+ eval "exec perl -S \$0 \$*"
+ if \$running_under_some_shell;
+
+# $Id: patsnap.SH,v 3.0.1.2 1994/01/24 14:33:08 ram Exp $
+#
+# Copyright (c) 1991-1993, Raphael Manfredi
+#
+# You may redistribute only under the terms of the Artistic Licence,
+# as specified in the README file that comes with the distribution.
+# You may reuse parts of this distribution only within the terms of
+# that same Artistic Licence; a copy of which may be found at the root
+# of the source tree for dist 3.0.
+#
+# $Log: patsnap.SH,v $
+# Revision 3.0.1.2 1994/01/24 14:33:08 ram
+# patch16: now prefix error messages with program's name
+# patch16: added ~/.dist_profile awareness
+#
+# Revision 3.0.1.1 1993/08/24 12:22:08 ram
+# patch3: created
+#
+
+\$version = '$VERSION';
+\$patchlevel = '$PATCHLEVEL';
+!GROK!THIS!
+cat >>patsnap <<'!NO!SUBS!'
+
+$progname = &profile; # Read ~/.dist_profile
+require 'getopts.pl';
+&usage unless $#ARGV >= 0;
+&usage unless &Getopts("aho:V");
+
+$SNAPSHOT = 'SNAPSHOT'; # Default snapshot file name
+
+if ($opt_V) {
+ print STDERR "$progname $version PL$patchlevel\n";
+ exit 0;
+} elsif ($opt_h) {
+ &usage;
+}
+
+&readpackage;
+
+$RCSEXT = ',v' unless $RCSEXT;
+$TOPDIR = ''; # We are at the top-level directory
+$SNAPSHOT = $opt_o if $opt_o;
+
+if ($opt_a) {
+ open(MANI,"MANIFEST.new") || die "$progname: can't read MANIFEST.new: $!\n";
+ @ARGV = ();
+ while (<MANI>) {
+ chop;
+ s|^\./||;
+ next if m|^patchlevel.h|; # Special file
+ ($_) = split(' ');
+ next if -d;
+ push(@ARGV,$_);
+ }
+ close MANI;
+}
+
+open(SNAPSHOT, ">$SNAPSHOT") || die "$progname: can't create $SNAPSHOT: $!\n";
+
+foreach $file (@ARGV) {
+ $files = &rcsargs($file);
+ @files = split(' ',$files);
+ $revs=0;
+ $rlog = `rlog -r$baserev -r$revbranch $files 2>&1`;
+ ($revs) = ($rlog =~ /selected revisions: (\d+)/);
+ if (!$revs) {
+ print "$progname: $file has never been checked in--skipping\n";
+ next;
+ }
+ elsif ($revs == 1) {
+ print "$progname: last revision for $file is $baserev.\n";
+ print SNAPSHOT "$file\t$baserev\n";
+ }
+ else {
+ ($lastrev) = ($rlog =~ /revision $revbranch\.(\d+)/);
+ print "$progname: last revision for $file is $revbranch.$lastrev.\n";
+ print SNAPSHOT "$file\t$revbranch.$lastrev\n";
+ }
+}
+
+close SNAPSHOT;
+
+sub usage {
+ print STDERR <<EOM;
+Usage: $progname [-ahV] [-o snapshot] [filelist]
+ -a : all the files in MANIFEST.new
+ -h : print this message and exit
+ -o : specify snapshot file output (default $SNAPSHOT)
+ -V : print version number and exit
+EOM
+ exit 1;
+}
+
+!NO!SUBS!
+$grep -v '^;#' ../pl/package.pl >>patsnap
+$grep -v '^;#' ../pl/rcsargs.pl >>patsnap
+$grep -v '^;#' ../pl/comment.pl >>patsnap
+$grep -v '^;#' ../pl/tilde.pl >>patsnap
+$grep -v '^;#' ../pl/profile.pl >>patsnap
+chmod +x patsnap
+$eunicefix patsnap