aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Eßer <[email protected]>2018-12-15 16:53:15 +0000
committerStefan Eßer <[email protected]>2018-12-15 16:53:15 +0000
commit385e98080cab314f10c0ab920f86a54ce0f2cdc0 (patch)
treefb027bbe41d4fbe359b13697cff43838ebd5b920
parent855acb84ca45f5aa1df94d1f2dd4b5e3e4c58c0e (diff)
downloadsrc-385e98080cab.tar.gz
src-385e98080cab.zip
Remove CTM from 13-CURRENT after the release of FreeBSD-12.0.
The removal (and creation of a port) has been pre-announced in UPDATING 1 month ago. Packages are available for all supported FreeBSD vesions. I did not think that another entry in UPDATING is required to note the actual removal. No MFC is planned - CTM shall be kept in base for all releases up to 12.x. Reviewed by: rgrimes Approved by: imp, bcr (manpages) Relnotes: yes Differential Revision: https://reviews.freebsd.org/D17935
Notes
Notes: svn path=/head/; revision=342126
-rw-r--r--share/man/man5/src.conf.54
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc12
-rw-r--r--tools/build/options/WITHOUT_CTM4
-rw-r--r--usr.sbin/Makefile1
-rw-r--r--usr.sbin/ctm/Makefile5
-rw-r--r--usr.sbin/ctm/Makefile.inc5
-rw-r--r--usr.sbin/ctm/README89
-rw-r--r--usr.sbin/ctm/ctm/Makefile24
-rw-r--r--usr.sbin/ctm/ctm/Makefile.depend18
-rw-r--r--usr.sbin/ctm/ctm/ctm.1336
-rw-r--r--usr.sbin/ctm/ctm/ctm.5182
-rw-r--r--usr.sbin/ctm/ctm/ctm.c336
-rw-r--r--usr.sbin/ctm/ctm/ctm.h163
-rw-r--r--usr.sbin/ctm/ctm/ctm_ed.c116
-rw-r--r--usr.sbin/ctm/ctm/ctm_input.c136
-rw-r--r--usr.sbin/ctm/ctm/ctm_pass1.c254
-rw-r--r--usr.sbin/ctm/ctm/ctm_pass2.c303
-rw-r--r--usr.sbin/ctm/ctm/ctm_pass3.c297
-rw-r--r--usr.sbin/ctm/ctm/ctm_passb.c144
-rw-r--r--usr.sbin/ctm/ctm/ctm_syntax.c69
-rw-r--r--usr.sbin/ctm/ctm_dequeue/Makefile13
-rw-r--r--usr.sbin/ctm/ctm_dequeue/Makefile.depend17
-rw-r--r--usr.sbin/ctm/ctm_dequeue/ctm_dequeue.c212
-rw-r--r--usr.sbin/ctm/ctm_rmail/Makefile10
-rw-r--r--usr.sbin/ctm/ctm_rmail/Makefile.depend17
-rw-r--r--usr.sbin/ctm/ctm_rmail/ctm_rmail.1510
-rw-r--r--usr.sbin/ctm/ctm_rmail/ctm_rmail.c672
-rw-r--r--usr.sbin/ctm/ctm_rmail/error.c102
-rw-r--r--usr.sbin/ctm/ctm_rmail/error.h5
-rw-r--r--usr.sbin/ctm/ctm_rmail/options.h139
-rw-r--r--usr.sbin/ctm/ctm_smail/Makefile13
-rw-r--r--usr.sbin/ctm/ctm_smail/Makefile.depend17
-rw-r--r--usr.sbin/ctm/ctm_smail/ctm_smail.c497
-rw-r--r--usr.sbin/ctm/mkCTM/Makefile25
-rw-r--r--usr.sbin/ctm/mkCTM/ctm_conf.cvs-cur9
-rw-r--r--usr.sbin/ctm/mkCTM/ctm_conf.ports-cur7
-rw-r--r--usr.sbin/ctm/mkCTM/ctm_conf.smp-cur7
-rw-r--r--usr.sbin/ctm/mkCTM/ctm_conf.src-cur9
-rw-r--r--usr.sbin/ctm/mkCTM/ctm_conf.src-special9
-rwxr-xr-xusr.sbin/ctm/mkCTM/dequeue6
-rw-r--r--usr.sbin/ctm/mkCTM/mkCTM188
-rw-r--r--usr.sbin/ctm/mkCTM/mkctm.c597
42 files changed, 0 insertions, 5579 deletions
diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5
index ca775507b338..ca4ad5abba06 100644
--- a/share/man/man5/src.conf.5
+++ b/share/man/man5/src.conf.5
@@ -479,10 +479,6 @@ is set explicitly)
Set to compile with CTF (Compact C Type Format) data.
CTF data encapsulates a reduced form of debugging information
similar to DWARF and the venerable stabs and is required for DTrace.
-.It Va WITHOUT_CTM
-Set to not build
-.Xr ctm 1
-and related utilities.
.It Va WITHOUT_CUSE
Set to not build CUSE-related programs and libraries.
.It Va WITHOUT_CXGBETOOL
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index 6065216badc1..da9be97d204a 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -1551,18 +1551,6 @@ OLD_FILES+=usr/bin/cpp
OLD_FILES+=usr/share/man/man1/cpp.1.gz
.endif
-.if ${MK_CTM} == no
-OLD_FILES+=usr/sbin/ctm
-OLD_FILES+=usr/sbin/ctm_dequeue
-OLD_FILES+=usr/sbin/ctm_rmail
-OLD_FILES+=usr/sbin/ctm_smail
-OLD_FILES+=usr/share/man/man1/ctm.1.gz
-OLD_FILES+=usr/share/man/man1/ctm_dequeue.1.gz
-OLD_FILES+=usr/share/man/man1/ctm_rmail.1.gz
-OLD_FILES+=usr/share/man/man1/ctm_smail.1.gz
-OLD_FILES+=usr/share/man/man5/ctm.5.gz
-.endif
-
.if ${MK_CUSE} == no
OLD_FILES+=usr/include/fs/cuse/cuse_defs.h
OLD_FILES+=usr/include/fs/cuse/cuse_ioctl.h
diff --git a/tools/build/options/WITHOUT_CTM b/tools/build/options/WITHOUT_CTM
deleted file mode 100644
index e436d9133968..000000000000
--- a/tools/build/options/WITHOUT_CTM
+++ /dev/null
@@ -1,4 +0,0 @@
-.\" $FreeBSD$
-Set to not build
-.Xr ctm 1
-and related utilities.
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index 390b470eb6d1..90fddeecf894 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -123,7 +123,6 @@ SUBDIR.${MK_BLUETOOTH}+= bluetooth
SUBDIR.${MK_BOOTPARAMD}+= bootparamd
SUBDIR.${MK_BSDINSTALL}+= bsdinstall
SUBDIR.${MK_BSNMP}+= bsnmpd
-SUBDIR.${MK_CTM}+= ctm
SUBDIR.${MK_CXGBETOOL}+= cxgbetool
SUBDIR.${MK_DIALOG}+= bsdconfig
SUBDIR.${MK_EFI}+= efivar efidp efibootmgr
diff --git a/usr.sbin/ctm/Makefile b/usr.sbin/ctm/Makefile
deleted file mode 100644
index 630aab0940dd..000000000000
--- a/usr.sbin/ctm/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# $FreeBSD$
-
-SUBDIR= ctm ctm_rmail ctm_smail ctm_dequeue
-
-.include <bsd.subdir.mk>
diff --git a/usr.sbin/ctm/Makefile.inc b/usr.sbin/ctm/Makefile.inc
deleted file mode 100644
index 78adccbf2426..000000000000
--- a/usr.sbin/ctm/Makefile.inc
+++ /dev/null
@@ -1,5 +0,0 @@
-# $FreeBSD$
-
-.if exists(${.CURDIR:H:H}/Makefile.inc)
-.include "${.CURDIR:H:H}/Makefile.inc"
-.endif
diff --git a/usr.sbin/ctm/README b/usr.sbin/ctm/README
deleted file mode 100644
index c89c07b277c2..000000000000
--- a/usr.sbin/ctm/README
+++ /dev/null
@@ -1,89 +0,0 @@
-# ----------------------------------------------------------------------------
-# "THE BEER-WARE LICENSE" (Revision 42):
-# <[email protected]> wrote this file. As long as you retain this notice you
-# can do whatever you want with this stuff. If we meet some day, and you think
-# this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
-# ----------------------------------------------------------------------------
-#
-# $FreeBSD$
-#
-
-What will I not find in this file ?
------------------------------------
-Instructions on how to obtain FreeBSD via CTM.
-Contact <[email protected]> for that.
-
-What is CTM ?
--------------
-CTM was originally "CVS Through eMail", but has since changed scope to be
-much more general.
-CTM is now meant to be the definitive way to make and apply a delta between
-two versions of a directory tree.
-There are two parts to this, making the delta and applying it. These are two
-entirely different things. CTM concentrates the computation-burden on the
-generation of the deltas, as a delta very often is applied more times than
-it is made. Second CTM tries to make the minimal size delta.
-
-Why not use diff/patch ?
-------------------------
-Good question. Primarily because diff and patch doesn't do their job very
-well. They don't deal with binary files (in this case files with '\0' or
-'\0377' characters in them or files that doesn't end in '\n') which isn't
-a big surprise: they were made to deal with text-files only. As a second
-gripe, with patch you send the entire file to delete it. Not particular
-efficient.
-
-So what does CTM do exactly ?
------------------------------
-CTM will produce a file, (a delta) containing the instructions and data needed
-to take another copy of the tree from the old to the new status. CTM means to
-do this in the exact sense, and therefore the delta contains MD5 checksums to
-verify that the tree it is applied to is indeed in the state CTM expects.
-
-This means that if you have modified the tree locally, CTM might not be able
-to upgrade your copy.
-
-How do I make a CTM-delta ?
----------------------------
-
-Read the source, and be prepared to have 2 copies of the tree; One is
-the reference ("From") tree, and the other is the delta ("To") tree.
-The mkCTM script will create the CTM diff of the differences between
-the reference tree and the delta tree. A lot of scratch space is
-required, and your machine will work hard.
-
-How do I apply a CTM-delta ?
-----------------------------
-You pass it to the 'ctm' command. You can pass a CTM-delta on stdin, or
-you can give the filename as an argument. If you do the latter, you make
-life a lot easier for your self, since the program can accept gzip'ed files
-and since it will not have to make a temporary copy of your file. You can
-specify multiple deltas at one time, they will be processed one at a time.
-
-The ctm command runs in a number of passes. It will process the entire
-input file in each pass, before commencing with the next pass.
-
-Pass 1 will validate that the input file is OK. The syntax, the data and
-the global MD5 checksum will be checked. If any of these fail, ctm will
-never be able to do anything with the file, so it will simply reject it.
-
-Pass 2 will validate that the directory tree is in the state expected by
-the CTM-delta. This is done by looking for files and directories which
-should/should not exists and by checking the MD5 checksums of files.
-
-Pass 3 will actually apply the delta.
-
-Should I delete the delta when I have applied it ?
---------------------------------------------------
-No. You might want to selectively reconstruct a file latter on.
-
-Why is CTM not being maintained?
---------------------------------
-Because CVSUP has improved on the concept quite a bit, and is now
-the method of choice.
-
-Is there a pointer to this whole glorious saga?
------------------------------------------------
-You bet! http://phk.freebsd.dk/sagas/ctm.html
-
-Poul-Henning
diff --git a/usr.sbin/ctm/ctm/Makefile b/usr.sbin/ctm/ctm/Makefile
deleted file mode 100644
index 5f72f05bac9e..000000000000
--- a/usr.sbin/ctm/ctm/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-# ----------------------------------------------------------------------------
-# "THE BEER-WARE LICENSE" (Revision 42):
-# <[email protected]> wrote this file. As long as you retain this notice you
-# can do whatever you want with this stuff. If we meet some day, and you think
-# this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
-# ----------------------------------------------------------------------------
-#
-# $FreeBSD$
-
-PROG= ctm
-MAN= ctm.1 ctm.5
-SRCS= ctm.c ctm_input.c ctm_pass1.c ctm_pass2.c ctm_pass3.c \
- ctm_passb.c ctm_syntax.c ctm_ed.c
-
-NOTYET= ctm_ed.c
-
-LIBADD= md
-
-WARNS?= 2
-
-.if exists(${.CURDIR:H:H}/Makefile.inc)
-.include "${.CURDIR:H:H}/Makefile.inc"
-.endif
-.include <bsd.prog.mk>
diff --git a/usr.sbin/ctm/ctm/Makefile.depend b/usr.sbin/ctm/ctm/Makefile.depend
deleted file mode 100644
index 31fbf9bc2f9f..000000000000
--- a/usr.sbin/ctm/ctm/Makefile.depend
+++ /dev/null
@@ -1,18 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libmd \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/ctm/ctm/ctm.1 b/usr.sbin/ctm/ctm/ctm.1
deleted file mode 100644
index ab0557f872b0..000000000000
--- a/usr.sbin/ctm/ctm/ctm.1
+++ /dev/null
@@ -1,336 +0,0 @@
-.\" ----------------------------------------------------------------------------
-.\" "THE BEER-WARE LICENSE" (Revision 42):
-.\" <[email protected]> wrote this file. As long as you retain this notice you
-.\" can do whatever you want with this stuff. If we meet some day, and you think
-.\" this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
-.\" ----------------------------------------------------------------------------
-.\"
-.\" This manual page is partially obtained from Poul-Hennings CTM README
-.\" file.
-.\"
-.\" CTM and ctm(1) by <[email protected]>
-.\"
-.\" $FreeBSD$
-.\"
-.Dd November 15, 2018
-.Dt CTM 1
-.Os
-.Sh NAME
-.Nm ctm
-.Nd source code mirror program
-.Sh SYNOPSIS
-.Nm
-.Op Fl cFklquv
-.Op Fl b Ar basedir
-.Op Fl B Ar backup-file
-.Op Fl e Ar include-regex
-.Op Fl t Ar tar-command
-.Op Fl T Ar tmpdir
-.Op Fl V Ar level
-.Op Fl x Ar exclude-regex
-.Ar
-.Sh DESCRIPTION
-The
-.Nm
-utility was originally
-.Dq Cvs Through eMail ,
-but now instead it seems more fitting to call it
-.Dq Current Through eMail .
-.Pp
-The
-.Nm
-utility is now meant to be the definitive way to make and apply a delta between
-two versions of a directory tree.
-.Pp
-There are two parts to this, making the delta and applying it.
-These are two
-entirely different things.
-.Ss Usage
-To apply a CTM delta, you pass it to the
-.Nm
-command.
-You can pass a CTM delta on stdin, or you can give the
-filename as an argument.
-If you do the latter, you make life a lot
-easier for your self, since the program can accept gzip'ed files and
-since it will not have to make a temporary copy of your file.
-You can
-specify multiple deltas at one time, they will be processed one at a
-time.
-Deltas that are already applied will be ignored.
-.Pp
-The
-.Nm
-command runs in a number of passes.
-It will process the entire
-input file in each pass, before commencing with the next pass.
-.Pp
-Before working on a file
-.Ar name
-.Nm
-first checks for the existence of the file
-.Ar name.ctm .
-If this file exists,
-.Nm
-works on it instead.
-.Pp
-Pass 1 will verify that the input file is OK.
-The syntax, the data
-and the global MD5 checksum will be checked.
-If any of these fail,
-.Nm
-will simply reject the input file.
-.Pp
-Pass 2 will validate that the directory tree is in the state expected by
-the CTM delta.
-This is done by looking for files and directories which
-should/should not exist and by checking the MD5 checksums of files.
-.Pp
-If a
-.Ar backup-file
-had been specified using the
-.Fl B
-option, all files that would be modified by this
-.Nm
-invocation are backed up
-to this file using the archiver command specified by the
-.Fl t
-option.
-The default archiver command is
-.Nm "tar -rf %s -T -" .
-.Pp
-Pass 3 will actually apply the delta.
-.Pp
-The list of files that would be modified by
-.Nm
-is subject to filtering regular expressions specified
-using the
-.Fl e
-and
-.Fl x
-options.
-The
-.Fl e
-and
-.Fl x
-options are applied in order of appearance on the command line.
-The last
-filter that matched a given file name determines whether the file would be
-operated on or left alone by
-.Nm .
-.Pp
-The
-.Nm
-utility
-will extract the file hierarchy below its working directory.
-Absolute
-filenames or filenames containing references through
-.Sq Pa .\&
-and
-.Sq Pa ..\&
-are explicitly prohibited as a security measure.
-.Ss Options
-.Bl -tag -width indent
-.It Fl b Ar basedir
-Prepend the path
-.Ar basedir
-to every filename.
-.It Fl B Ar backup-file
-Backup all files that would be modified by this CTM run to
-.Ar backup-file .
-If any filters are specified using the
-.Fl e
-and
-.Fl x
-options, then the final set of files backed up are those that would be
-modified by CTM after the filters are applied.
-.It Fl c
-Check it out, do not do anything.
-.It Fl e Ar regular_expression
-Match each name in the CTM file against
-.Ar regular_expression ,
-and if it matches process the file, otherwise leave it alone.
-There may be
-any number of these options.
-Use of this option disables the
-.Pa .ctm_status
-sequence number checks.
-For example, the expression
-.Ic ^usr.sbin/ctm
-for example, will select the
-.Pa usr.sbin/ctm
-source directory and all pathnames under it.
-.Pp
-Pathnames can be disabled from being considered by CTM using the
-.Fl x
-option.
-.It Fl F
-Force.
-.It Fl k
-Keep files and directories and do not remove them even if the CTM file
-specifies they are to be removed.
-If the
-.Fl B
-option is specified, these files and directories will not be backed up.
-.It Fl l
-List files that would be modified by this invocation of CTM and the
-actions that would be performed on them.
-Use of the
-.Fl l
-option disables the
-.Pa .ctm_status
-checks and integrity checks on the source tree being operated on.
-The
-.Fl l
-option can be combined with the
-.Fl e
-and
-.Fl x
-options to determine which files would be modified by the given set of
-command line options.
-.It Fl q
-Tell us less.
-.It Fl t Ar tar-command
-Use
-.Ar tar-command
-instead of the default archiver
-.Nm tar .
-This option takes effect only if a backup file had been specified using the
-.Fl B
-option.
-A %s in the tar command will be replaced by the name of the backup
-file.
-.It Fl T Ar tmpdir
-Put temporary files under
-.Ar tmpdir .
-.It Fl u
-Set modification time of created and modified files to the CTM delta
-creation time.
-.It Fl v
-Tell us more.
-.It Fl V Ar level
-Tell us more.
-.Ar Level
-is the level of verbosity.
-.It Fl x Ar regular_expression
-Match each name in the CTM file against
-.Ar regular_expression
-and if it matches, leave the file alone.
-There may be any number of these
-options.
-Use of this option disables the
-.Pa .ctm_status
-sequence number checks.
-.Pp
-Pathnames can be selected for CTM's consideration using the
-.Fl e
-option.
-.El
-.Sh SECURITY
-On its own, CTM is an insecure protocol
-- there is no authentication performed that the
-changes applied to the source code were sent by a
-trusted party, and so care should be taken if the
-CTM deltas are obtained via an unauthenticated
-medium such as regular email.
-It is a relatively simple matter for an attacker
-to forge a CTM delta to replace or precede the
-legitimate one and insert malicious code into your
-source tree.
-If the legitimate delta is somehow prevented from
-arriving, this will go unnoticed until a later
-delta attempts to touch the same file, at which
-point the MD5 checksum will fail.
-.Pp
-To remedy this insecurity, CTM pieces generated by
-FreeBSD.org are cryptographically signed in a
-format compatible with the GNU Privacy Guard
-utility, available in /usr/ports/security/gpg, and
-the Pretty Good Privacy v5 utility,
-/usr/ports/security/pgp5.
-The relevant public key can be obtained by
-fingering [email protected].
-.Pp
-CTM deltas which are thus signed cannot be
-undetectably altered by an attacker.
-Therefore it is recommended that you make use of
-GPG or PGP5 to verify the signatures if you
-receive your CTM deltas via email.
-.Sh ENVIRONMENT
-.Ev TMPDIR ,
-if set to a pathname, will cause ctm to use that pathname
-as the location of temporary file.
-See
-.Xr tempnam 3 ,
-for more details on this.
-The same effect may be achieved with the
-.Fl T
-flag.
-.Sh FILES
-.Pa .ctm_status
-contains the sequence number of the last CTM delta applied.
-Changing
-or removing this file will greatly confuse
-.Nm .
-.Pp
-Using the
-.Fl e
-and
-.Fl x
-options can update a partial subset of the source tree and causes sources
-to be in an inconsistent state.
-It is assumed that you know what you are
-doing when you use these options.
-.Sh EXAMPLES
-.Bd -literal
-cd ~cvs
-/usr/sbin/ctm ~ctm/cvs-*
-.Ed
-.Pp
-To extract and patch all sources under `lib'
-.Bd -literal
-cd ~/lib-srcs
-/usr/sbin/ctm -e '^lib' ~ctm/src-cur*
-.Ed
-.Sh DIAGNOSTICS
-Numerous messages, hopefully self-explanatory.
-The
-.Dq noise level
-can be adjusted with the
-.Fl q ,
-.Fl v
-and
-.Fl V
-options.
-.Sh SEE ALSO
-.Xr ctm_dequeue 1 ,
-.Xr ctm_rmail 1 ,
-.Xr ctm_smail 1 ,
-.Xr ctm 5
-.Rs
-.%T "Miscellaneous CTM on FreeBSD Resources"
-.%U http://ctm.berklix.org
-.Re
-.Sh HISTORY
-Initial trials were run during the work on
-.Fx 1.1.5 ,
-and many bugs and
-methods were hashed out.
-.Pp
-The
-.Nm
-command appeared in
-.Fx 2.1 .
-.Pp
-The latest
-.Nm
-code has been made available as a port (misc/ctm) in preparation of removal
-from base in
-.Fx 13.0 .
-.Sh AUTHORS
-.An -nosplit
-The CTM system has been designed and implemented by
-.An Poul-Henning Kamp Aq Mt [email protected] .
-.Pp
-.An Joerg Wunsch Aq Mt [email protected]
-wrote this man-page.
diff --git a/usr.sbin/ctm/ctm/ctm.5 b/usr.sbin/ctm/ctm/ctm.5
deleted file mode 100644
index e48b09fc85bd..000000000000
--- a/usr.sbin/ctm/ctm/ctm.5
+++ /dev/null
@@ -1,182 +0,0 @@
-.\" ----------------------------------------------------------------------------
-.\" "THE BEER-WARE LICENSE" (Revision 42):
-.\" <[email protected]> wrote this file. As long as you retain this notice you
-.\" can do whatever you want with this stuff. If we meet some day, and you think
-.\" this stuff is worth it, you can buy me a beer in return. Joerg Wunsch
-.\" ----------------------------------------------------------------------------
-.\"
-.\" This manual page is partially obtained from Poul-Hennings CTM README
-.\" file.
-.\"
-.\" CTM and ctm(1) by <[email protected]>
-.\"
-.\" $FreeBSD$
-.\"
-.Dd March 25, 1995
-.Dt CTM 5
-.Os
-.Sh NAME
-.Nm ctm
-.Nd source code mirror system
-.Sh DESCRIPTION
-The
-.Nm
-transfers data in a specific file format, called a CTM delta.
-.Pp
-CTM deltas consist of control lines and data chunks.
-Each control
-line starts with the letters
-.Dq CTM ,
-followed by a CTM statement and control data, and ends with a '\en'
-character.
-.Pp
-Data chunks always belong to the preceding control line, and the
-last field on that control line is the number of bytes in the data
-chunk.
-A trailing newline '\en' character follows each data chunk, this
-newline is not part of the chunk and is not included in the count.
-.Pp
-The CTM statements are as follows.
-.Bl -tag -width indent
-.It _BEGIN Ar version name number timestamp prefix
-This is the overall begin of a CTM delta file.
-The
-.Ar version
-field must match the program version
-(currently 2.0).
-.Ar Name
-is the name and
-.Ar number
-the sequence number of the CTM service, it is matched against the file
-.Pa .ctm_status
-to see if the delta has already been applied.
-.Ar Timestamp
-contains the year, month, day, hour, minute, and second of the
-time of delta creation for reference
-(followed by the letter
-.Sq Z
-meaning this is a UTC timestamp).
-The
-.Ar prefix
-field is currently not implemented.
-.It _END Ar md5
-This statement ends the CTM delta, the global
-.Ar md5
-checksum is matched against the MD5 checksum of the entire delta, up to
-and including the space (0x20) character following ``_END''.
-.It \&FM Ar name uid gid mode md5 count
-Make the file
-.Ar name ,
-the original file had the uid
-.Ar uid
-(numerical, decimal),
-the gid
-.Ar gid
-(numerical, decimal),
-mode
-.Ar mode
-(numerical, octal),
-and the MD5 checksum
-.Ar md5 .
-.Pp
-The following
-.Ar count
-bytes data are the contents of the new file.
-.It \&FS Ar name uid gid mode md5before md5after count
-Substitute the contents of file
-.Ar name ,
-the original file had the new uid
-.Ar uid
-(numerical, decimal),
-the new gid
-.Ar gid
-(numerical, decimal),
-new mode
-.Ar mode
-(numerical, octal),
-the old MD5 checksum
-.Ar md5before ,
-and the new MD5 checksum
-.Ar md5after .
-.Pp
-The following
-.Ar count
-bytes data are the contents of the new file.
-.Pp
-File substitution is used if the commands to edit a file would exceed
-the total file length, so substituting it is more efficient.
-.It \&FN Ar name uid gid mode md5before md5after count
-Edit the file
-.Ar name .
-The arguments are as above, but the data sections contains an
-.Xr diff 1
--n script which should be applied to the file in question.
-.It \&FR Ar name md5
-Remove the file
-.Ar name ,
-which must match the MD5 checksum
-.Ar md5 .
-.It \&AS Ar name uid gid mode
-The original file
-.Ar name
-changed its owner to
-.Ar uid ,
-its group to
-.Ar gid ,
-and/or its mode to
-.Ar mode .
-.It \&DM Ar name uid gid mode
-The directory
-.Ar name
-is to be created, it had originally the owner
-.Ar uid ,
-group
-.Ar gid ,
-and mode
-.Ar mode .
-.It \&DR Ar name
-The directory
-.Ar name
-is to be removed.
-.El
-.Sh EXAMPLES
-In the following example, long lines have been folded to make them
-printable
-(marked by backslashes).
-.Bd -literal
-CTM_BEGIN 2.0 cvs-cur 485 19950324214652Z .
-CTMFR src/sys/gnu/i386/isa/scd.c,v 5225f13aa3c7e458f9dd0d4bb637b18d
-CTMFR src/sys/gnu/i386/isa/scdreg.h,v e5af42b8a06f2c8030b93a7d71afb223
-CTMDM src/sys/gnu/i386/isa/Attic 0 552 775
-CTMFS .ctm_status 545 552 664 d9ccd2a84a9dbb8db56ba85663adebf0 \\
-e2a10c6f66428981782a0a18a789ee2e 12
-cvs-cur 485
-
-CTMFN CVSROOT/commitlogs/gnu 545 552 664 \\
-5d7bc3549140d860bd9641b5782c002d 7fb04ed84b48160c9b8eea84b4c0b6e3 394
-a6936 21
-ache 95/03/24 09:59:50
-
- Modified: gnu/lib/libdialog kernel.c prgbox.c
- Log:
-[...]
-CTM_END 74ddd298d76215ae45a077a4b6a74e9c
-.Ed
-.Sh SEE ALSO
-.Xr ctm 1 ,
-.Xr ctm_rmail 1 ,
-.Xr ed 1
-.Sh HISTORY
-Initial trials ran during the
-.Fx 1.1.5 ,
-and many bugs and
-methods were hashed out.
-The CTM system has been made publicly available in
-.Fx 2.1 .
-.Sh AUTHORS
-.An -nosplit
-The CTM system has been designed and implemented by
-.An Poul-Henning Kamp Aq Mt [email protected] .
-.Pp
-.An Joerg Wunsch Aq Mt [email protected]
-wrote this man-page.
diff --git a/usr.sbin/ctm/ctm/ctm.c b/usr.sbin/ctm/ctm/ctm.c
deleted file mode 100644
index 9674baf8e8bc..000000000000
--- a/usr.sbin/ctm/ctm/ctm.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <[email protected]> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * $FreeBSD$
- *
- * This is the client program of 'CTM'. It will apply a CTM-patch to a
- * collection of files.
- *
- * Options we'd like to see:
- *
- * -a Attempt best effort.
- * -d <int> Debug TBD.
- * -m <mail-addr> Email me instead.
- * -r <name> Reconstruct file.
- * -R <file> Read list of files to reconstruct.
- *
- * Options we have:
- * -b <dir> Base-dir
- * -B <file> Backup to tar-file.
- * -t Tar command (default as in TARCMD).
- * -c Check it out, don't do anything.
- * -F Force
- * -q Tell us less.
- * -T <tmpdir>. Temporary files.
- * -u Set all file modification times to the timestamp
- * -v Tell us more.
- * -V <level> Tell us more level = number of -v
- * -k Keep files and directories that would have been removed.
- * -l List actions.
- *
- * Options we don't actually use:
- * -p Less paranoid.
- * -P Paranoid.
- */
-
-#define EXTERN /* */
-#include <paths.h>
-#include "ctm.h"
-
-#define CTM_STATUS ".ctm_status"
-
-extern int Proc(char *, unsigned applied);
-
-int
-main(int argc, char **argv)
-{
- int stat=0, err=0;
- int c;
- unsigned applied = 0;
- FILE *statfile;
- struct CTM_Filter *nfilter = NULL; /* new filter */
- u_char * basedir;
-
- basedir = NULL;
- Verbose = 1;
- Paranoid = 1;
- SetTime = 0;
- KeepIt = 0;
- ListIt = 0;
- BackupFile = NULL;
- TarCmd = TARCMD;
- LastFilter = FilterList = NULL;
- TmpDir = getenv("TMPDIR");
- if (TmpDir == NULL)
- TmpDir = strdup(_PATH_TMP);
- setbuf(stderr,0);
- setbuf(stdout,0);
-
- while((c=getopt(argc,argv,"ab:B:cd:e:Fklm:pPqr:R:t:T:uV:vx:")) != -1) {
- switch (c) {
- case 'b': basedir = optarg; break; /* Base Directory */
- case 'B': BackupFile = optarg; break;
- case 'c': CheckIt++; break; /* Only check it */
- case 'F': Force = 1; break;
- case 'k': KeepIt++; break; /* Don't do removes */
- case 'l': ListIt++; break; /* Only list actions and files */
- case 'p': Paranoid--; break; /* Less Paranoid */
- case 'P': Paranoid++; break; /* More Paranoid */
- case 'q': Verbose--; break; /* Quiet */
- case 't': TarCmd = optarg; break; /* archiver command */
- case 'T': TmpDir = optarg; break; /* set temporary directory */
- case 'u': SetTime++; break; /* Set timestamp on files */
- case 'v': Verbose++; break; /* Verbose */
- case 'V': sscanf(optarg,"%d", &c); /* Verbose */
- Verbose += c;
- break;
- case 'e': /* filter expressions */
- case 'x':
- if (NULL == (nfilter = Malloc(sizeof(struct CTM_Filter)))) {
- warnx("out of memory for expressions: \"%s\"", optarg);
- stat++;
- break;
- }
-
- (void) memset(nfilter, 0, sizeof(struct CTM_Filter));
-
- if (0 != (err =
- regcomp(&nfilter->CompiledRegex, optarg, REG_NOSUB))) {
-
- char errmsg[128];
-
- regerror(err, &nfilter->CompiledRegex, errmsg,
- sizeof(errmsg));
- warnx("regular expression: \"%s\"", errmsg);
- stat++;
- break;
- }
-
- /* note whether the filter enables or disables on match */
- nfilter->Action =
- (('e' == c) ? CTM_FILTER_ENABLE : CTM_FILTER_DISABLE);
-
- /* link in the expression into the list */
- nfilter->Next = NULL;
- if (NULL == FilterList) {
- LastFilter = FilterList = nfilter; /* init head and tail */
- } else { /* place at tail */
- LastFilter->Next = nfilter;
- LastFilter = nfilter;
- }
- break;
- case ':':
- warnx("option '%c' requires an argument",optopt);
- stat++;
- break;
- case '?':
- warnx("option '%c' not supported",optopt);
- stat++;
- break;
- default:
- warnx("option '%c' not yet implemented",optopt);
- break;
- }
- }
-
- if(stat) {
- warnx("%d errors during option processing",stat);
- return Exit_Pilot;
- }
- fprintf(stderr, "CTM will be removed from FreeBSD-13, and will be "
- "provided as a port (misc/ctm) or package (ctm).\n\n");
-
- stat = Exit_Done;
- argc -= optind;
- argv += optind;
-
- if (basedir == NULL) {
- Buffer = (u_char *)Malloc(BUFSIZ + strlen(SUBSUFF) +1);
- CatPtr = Buffer;
- *Buffer = '\0';
- } else {
- Buffer = (u_char *)Malloc(strlen(basedir)+ BUFSIZ + strlen(SUBSUFF) +1);
- strcpy(Buffer, basedir);
- CatPtr = Buffer + strlen(basedir);
- if (CatPtr[-1] != '/') {
- strcat(Buffer, "/");
- CatPtr++;
- }
- }
- strcat(Buffer, CTM_STATUS);
-
- if(ListIt)
- applied = 0;
- else
- if((statfile = fopen(Buffer, "r")) == NULL) {
- if (Verbose > 0)
- warnx("warning: %s not found", Buffer);
- } else {
- fscanf(statfile, "%*s %u", &applied);
- fclose(statfile);
- }
-
- if(!argc)
- stat |= Proc("-", applied);
-
- while(argc-- && stat == Exit_Done) {
- stat |= Proc(*argv++, applied);
- stat &= ~(Exit_Version | Exit_NoMatch);
- }
-
- if(stat == Exit_Done)
- stat = Exit_OK;
-
- if(Verbose > 0)
- warnx("exit(%d)",stat);
-
- if (FilterList)
- for (nfilter = FilterList; nfilter; ) {
- struct CTM_Filter *tmp = nfilter->Next;
- Free(nfilter);
- nfilter = tmp;
- }
- return stat;
-}
-
-int
-Proc(char *filename, unsigned applied)
-{
- FILE *f;
- int i;
- char *p = strrchr(filename,'.');
-
- if(!strcmp(filename,"-")) {
- p = 0;
- f = stdin;
- } else if(p && (!strcmp(p,".gz") || !strcmp(p,".Z"))) {
- p = alloca(20 + strlen(filename));
- strcpy(p,"gunzip < ");
- strcat(p,filename);
- f = popen(p,"r");
- if(!f) { warn("%s", p); return Exit_Garbage; }
- } else {
- p = 0;
- f = fopen(filename,"r");
- }
- if(!f) {
- warn("%s", filename);
- return Exit_Garbage;
- }
-
- if(Verbose > 1)
- fprintf(stderr,"Working on <%s>\n",filename);
-
- Delete(FileName);
- FileName = String(filename);
-
- /* If we cannot seek, we're doomed, so copy to a tmp-file in that case */
- if(!p && -1 == fseek(f,0,SEEK_END)) {
- char *fn;
- FILE *f2;
- int fd;
-
- if (asprintf(&fn, "%s/CTMclient.XXXXXXXXXX", TmpDir) == -1) {
- fprintf(stderr, "Cannot allocate memory\n");
- fclose(f);
- return Exit_Broke;
- }
- if ((fd = mkstemp(fn)) == -1 || (f2 = fdopen(fd, "w+")) == NULL) {
- warn("%s", fn);
- free(fn);
- if (fd != -1)
- close(fd);
- fclose(f);
- return Exit_Broke;
- }
- unlink(fn);
- if (Verbose > 0)
- fprintf(stderr,"Writing tmp-file \"%s\"\n",fn);
- free(fn);
- while(EOF != (i=getc(f)))
- if(EOF == putc(i,f2)) {
- fclose(f2);
- return Exit_Broke;
- }
- fclose(f);
- f = f2;
- }
-
- if(!p)
- rewind(f);
-
- if((i=Pass1(f, applied)))
- goto exit_and_close;
-
- if(ListIt) {
- i = Exit_Done;
- goto exit_and_close;
- }
-
- if(!p) {
- rewind(f);
- } else {
- pclose(f);
- f = popen(p,"r");
- if(!f) { warn("%s", p); return Exit_Broke; }
- }
-
- i=Pass2(f);
-
- if(!p) {
- rewind(f);
- } else {
- pclose(f);
- f = popen(p,"r");
- if(!f) { warn("%s", p); return Exit_Broke; }
- }
-
- if(i) {
- if((!Force) || (i & ~Exit_Forcible))
- goto exit_and_close;
- }
-
- if(CheckIt) {
- if (Verbose > 0)
- fprintf(stderr,"All checks out ok.\n");
- i = Exit_Done;
- goto exit_and_close;
- }
-
- /* backup files if requested */
- if(BackupFile) {
-
- i = PassB(f);
-
- if(!p) {
- rewind(f);
- } else {
- pclose(f);
- f = popen(p,"r");
- if(!f) { warn("%s", p); return Exit_Broke; }
- }
- }
-
- i=Pass3(f);
-
-exit_and_close:
- if(!p)
- fclose(f);
- else
- pclose(f);
-
- if(i)
- return i;
-
- if (Verbose > 0)
- fprintf(stderr,"All done ok\n");
-
- return Exit_Done;
-}
diff --git a/usr.sbin/ctm/ctm/ctm.h b/usr.sbin/ctm/ctm/ctm.h
deleted file mode 100644
index b733539bbd97..000000000000
--- a/usr.sbin/ctm/ctm/ctm.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <[email protected]> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * $FreeBSD$
- *
- */
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <md5.h>
-#include <regex.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <sys/time.h>
-
-#define VERSION "2.0"
-
-#define SUBSUFF ".ctm"
-#define TMPSUFF ".ctmtmp"
-#define TARCMD "tar -rf %s -T -"
-
-/* The fields... */
-#define CTM_F_MASK 0xff
-#define CTM_F_Name 0x01
-#define CTM_F_Uid 0x02
-#define CTM_F_Gid 0x03
-#define CTM_F_Mode 0x04
-#define CTM_F_MD5 0x05
-#define CTM_F_Count 0x06
-#define CTM_F_Bytes 0x07
-
-/* The qualifiers... */
-#define CTM_Q_MASK 0xff00
-#define CTM_Q_Name_File 0x0100
-#define CTM_Q_Name_Dir 0x0200
-#define CTM_Q_Name_New 0x0400
-#define CTM_Q_Name_Subst 0x0800
-#define CTM_Q_MD5_After 0x0100
-#define CTM_Q_MD5_Before 0x0200
-#define CTM_Q_MD5_Chunk 0x0400
-#define CTM_Q_MD5_Force 0x0800
-
-struct CTM_Syntax {
- char *Key; /* CTM key for operation */
- int *List; /* List of operations */
- };
-
-extern struct CTM_Syntax Syntax[];
-
-struct CTM_Filter {
- struct CTM_Filter *Next; /* next filter in the list */
- int Action; /* enable or disable */
- regex_t CompiledRegex; /* compiled regex */
-};
-
-#define CTM_FILTER_DISABLE 0
-#define CTM_FILTER_ENABLE 1
-
-#define Malloc malloc
-#define Free free
-#define Delete(foo) if (!foo) ; else {Free(foo); foo = 0; }
-#define String(foo) strdup(foo)
-
-#ifndef EXTERN
-# define EXTERN extern
-#endif
-EXTERN u_char *Version;
-EXTERN u_char *Name;
-EXTERN u_char *Nbr;
-EXTERN u_char *TimeStamp;
-EXTERN u_char *Prefix;
-EXTERN u_char *FileName;
-EXTERN u_char *TmpDir;
-EXTERN u_char *CatPtr;
-EXTERN u_char *Buffer;
-EXTERN u_char *BackupFile;
-EXTERN u_char *TarCmd;
-
-/*
- * Paranoid -- Just in case they should be after us...
- * 0 not at all.
- * 1 normal.
- * 2 somewhat.
- * 3 you bet!.
- *
- * Verbose -- What to tell mom...
- * 0 Nothing which wouldn't surprise.
- * 1 Normal.
- * 2 Show progress '.'.
- * 3 Show progress names, and actions.
- * 4 even more...
- * and so on
- *
- * ExitCode -- our Epitaph
- * 0 Perfect, all input digested, no problems
- * 1 Bad input, no point in retrying.
- * 2 Pilot error, commandline problem &c
- * 4 Out of resources.
- * 8 Destination-tree not correct.
- * 16 Destination-tree not correct, can force.
- * 32 Internal problems.
- *
- */
-
-EXTERN int Paranoid;
-EXTERN int Verbose;
-EXTERN int Exit;
-EXTERN int Force;
-EXTERN int CheckIt;
-EXTERN int KeepIt;
-EXTERN int ListIt;
-EXTERN int SetTime;
-EXTERN struct timeval Times[2];
-EXTERN struct CTM_Filter *FilterList;
-EXTERN struct CTM_Filter *LastFilter;
-
-#define Exit_OK 0
-#define Exit_Garbage 1
-#define Exit_Pilot 2
-#define Exit_Broke 4
-#define Exit_NotOK 8
-#define Exit_Forcible 16
-#define Exit_Mess 32
-#define Exit_Done 64
-#define Exit_Version 128
-#define Exit_NoMatch 256
-
-void Fatal_(int ln, char *fn, char *kind);
-#define Fatal(foo) Fatal_(__LINE__,__FILE__,foo)
-#define Assert() Fatal_(__LINE__,__FILE__,"Assert failed.")
-#define WRONG {Assert(); return Exit_Mess;}
-
-u_char * Ffield(FILE *fd, MD5_CTX *ctx,u_char term);
-u_char * Fname(FILE *fd, MD5_CTX *ctx,u_char term,int qual, int verbose);
-
-int Fbytecnt(FILE *fd, MD5_CTX *ctx, u_char term);
-
-u_char * Fdata(FILE *fd, int u_chars, MD5_CTX *ctx);
-
-#define GETFIELD(p,q) if(!((p)=Ffield(fd,&ctx,(q)))) return BADREAD
-#define GETFIELDCOPY(p,q) if(!((p)=Ffield(fd,&ctx,(q)))) return BADREAD; else p=String(p)
-#define GETBYTECNT(p,q) if(0 >((p)= Fbytecnt(fd,&ctx,(q)))) return BADREAD
-#define GETDATA(p,q) if(!((p) = Fdata(fd,(q),&ctx))) return BADREAD
-#define GETNAMECOPY(p,q,r,v) if(!((p)=Fname(fd,&ctx,(q),(r),(v)))) return BADREAD; else p=String(p)
-
-int Pass1(FILE *fd, unsigned applied);
-int Pass2(FILE *fd);
-int PassB(FILE *fd);
-int Pass3(FILE *fd);
-
-int ctm_edit(u_char *script, int length, char *filein, char *fileout);
diff --git a/usr.sbin/ctm/ctm/ctm_ed.c b/usr.sbin/ctm/ctm/ctm_ed.c
deleted file mode 100644
index c4d62428b280..000000000000
--- a/usr.sbin/ctm/ctm/ctm_ed.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <[email protected]> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * $FreeBSD$
- *
- */
-
-#include "ctm.h"
-
-int
-ctm_edit(u_char *script, int length, char *filein, char *fileout)
-{
- u_char *ep, cmd;
- int ln, ln2, iln, ret=0, c;
- FILE *fi=0,*fo=0;
-
- fi = fopen(filein,"r");
- if(!fi) {
- warn("%s", filein);
- return 8;
- }
-
- fo = fopen(fileout,"w");
- if(!fo) {
- warn("%s", fileout);
- fclose(fi);
- return 4;
- }
- iln = 1;
- for(ep=script;ep < script+length;) {
- cmd = *ep++;
- if(cmd != 'a' && cmd != 'd') { ret = 1; goto bye; }
- ln = 0;
- while(isdigit(*ep)) {
- ln *= 10;
- ln += (*ep++ - '0');
- }
- if(*ep++ != ' ') { ret = 1; goto bye; }
- ln2 = 0;
- while(isdigit(*ep)) {
- ln2 *= 10;
- ln2 += (*ep++ - '0');
- }
- if(*ep++ != '\n') { ret = 1; goto bye; }
-
-
- if(cmd == 'd') {
- while(iln < ln) {
- c = getc(fi);
- if(c == EOF) { ret = 1; goto bye; }
- putc(c,fo);
- if(c == '\n')
- iln++;
- }
- while(ln2) {
- c = getc(fi);
- if(c == EOF) { ret = 1; goto bye; }
- if(c != '\n')
- continue;
- ln2--;
- iln++;
- }
- continue;
- }
- if(cmd == 'a') {
- while(iln <= ln) {
- c = getc(fi);
- if(c == EOF) { ret = 1; goto bye; }
- putc(c,fo);
- if(c == '\n')
- iln++;
- }
- while(ln2) {
- c = *ep++;
- putc(c,fo);
- if(c != '\n')
- continue;
- ln2--;
- }
- continue;
- }
- ret = 1;
- goto bye;
- }
- while(1) {
- c = getc(fi);
- if(c == EOF) break;
- putc(c,fo);
- }
- ret = 0;
-bye:
- if(fi) {
- if(fclose(fi) != 0) {
- warn("%s", filein);
- ret = 1;
- }
- }
- if(fo) {
- if(fflush(fo) != 0) {
- warn("%s", fileout);
- ret = 1;
- }
- if(fclose(fo) != 0) {
- warn("%s", fileout);
- ret = 1;
- }
- }
- return ret;
-}
diff --git a/usr.sbin/ctm/ctm/ctm_input.c b/usr.sbin/ctm/ctm/ctm_input.c
deleted file mode 100644
index a04d3ebc3494..000000000000
--- a/usr.sbin/ctm/ctm/ctm_input.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <[email protected]> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * $FreeBSD$
- *
- */
-
-#include "ctm.h"
-
-/*---------------------------------------------------------------------------*/
-void
-Fatal_(int ln, char *fn, char *kind)
-{
- if(Verbose > 2)
- fprintf(stderr,"Fatal error. (%s:%d)\n",fn,ln);
- fprintf(stderr,"%s Fatal error: %s\n",FileName, kind);
-}
-#define Fatal(foo) Fatal_(__LINE__,__FILE__,foo)
-#define Assert() Fatal_(__LINE__,__FILE__,"Assert failed.")
-
-/*---------------------------------------------------------------------------*/
-/* get next field, check that the terminating whitespace is what we expect */
-u_char *
-Ffield(FILE *fd, MD5_CTX *ctx,u_char term)
-{
- static u_char buf[BUFSIZ];
- int i,l;
-
- for(l=0;;) {
- if((i=getc(fd)) == EOF) {
- Fatal("Truncated patch.");
- return 0;
- }
- buf[l++] = i;
- if(isspace(i))
- break;
- if(l >= sizeof buf) {
- Fatal("Corrupt patch.");
- printf("Token is too long.\n");
- return 0;
- }
- }
- buf[l] = '\0';
- MD5Update(ctx,buf,l);
- if(buf[l-1] != term) {
- Fatal("Corrupt patch.");
- fprintf(stderr,"Expected \"%s\" but didn't find it {%02x}.\n",
- term == '\n' ? "\\n" : " ",buf[l-1]);
- if(Verbose > 4)
- fprintf(stderr,"{%s}\n",buf);
- return 0;
- }
- buf[--l] = '\0';
- if(Verbose > 4)
- fprintf(stderr,"<%s>\n",buf);
- return buf;
-}
-
-int
-Fbytecnt(FILE *fd, MD5_CTX *ctx, u_char term)
-{
- u_char *p,*q;
- int u_chars=0;
-
- p = Ffield(fd,ctx,term);
- if(!p) return -1;
- for(q=p;*q;q++) {
- if(!isdigit(*q)) {
- Fatal("Bytecount contains non-digit.");
- return -1;
- }
- u_chars *= 10;
- u_chars += (*q - '0');
- }
- return u_chars;
-}
-
-u_char *
-Fdata(FILE *fd, int u_chars, MD5_CTX *ctx)
-{
- u_char *p = Malloc(u_chars+1);
-
- if(u_chars+1 != fread(p,1,u_chars+1,fd)) {
- Fatal("Truncated patch.");
- return 0;
- }
- MD5Update(ctx,p,u_chars+1);
- if(p[u_chars] != '\n') {
- if(Verbose > 3)
- printf("FileData wasn't followed by a newline.\n");
- Fatal("Corrupt patch.");
- return 0;
- }
- p[u_chars] = '\0';
- return p;
-}
-
-/*---------------------------------------------------------------------------*/
-/* get the filename in the next field, prepend BaseDir and give back the result
- strings. The sustitute filename is return (the one with the suffix SUBSUFF)
- if it exists and the qualifier contains CTM_Q_Name_Subst
- NOTA: Buffer is already initialize with BaseDir, CatPtr is the insertion
- point on this buffer + the length test in Ffield() is enough for Fname() */
-
-u_char *
-Fname(FILE *fd, MD5_CTX *ctx,u_char term,int qual, int verbose)
-{
- u_char * p;
- struct stat st;
-
- if ((p = Ffield(fd,ctx,term)) == NULL) return(NULL);
-
- strcpy(CatPtr, p);
-
- if (!(qual & CTM_Q_Name_Subst)) return(Buffer);
-
- p = Buffer + strlen(Buffer);
-
- strcat(Buffer, SUBSUFF);
-
- if ( -1 == stat(Buffer, &st) ) {
- *p = '\0';
- } else {
- if(verbose > 2)
- fprintf(stderr,"Using %s as substitute file\n", Buffer);
- }
-
- return (Buffer);
-}
diff --git a/usr.sbin/ctm/ctm/ctm_pass1.c b/usr.sbin/ctm/ctm/ctm_pass1.c
deleted file mode 100644
index 2c981b750b5f..000000000000
--- a/usr.sbin/ctm/ctm/ctm_pass1.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <[email protected]> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * $FreeBSD$
- *
- */
-
-#include "ctm.h"
-#define BADREAD 1
-
-/*---------------------------------------------------------------------------*/
-/* Pass1 -- Validate the incoming CTM-file.
- */
-
-int
-Pass1(FILE *fd, unsigned applied)
-{
- u_char *p,*q;
- MD5_CTX ctx;
- int i,j,sep,cnt;
- u_char *md5=0,*name=0,*trash=0;
- struct CTM_Syntax *sp;
- int slashwarn=0, match=0, total_matches=0;
- unsigned current;
- char md5_1[33];
-
- if(Verbose>3)
- printf("Pass1 -- Checking integrity of incoming CTM-patch\n");
- MD5Init (&ctx);
-
- GETFIELD(p,' '); /* CTM_BEGIN */
- if(strcmp(p,"CTM_BEGIN")) {
- Fatal("Probably not a CTM-patch at all.");
- if(Verbose>3)
- fprintf(stderr,"Expected \"CTM_BEGIN\" got \"%s\".\n",p);
- return 1;
- }
-
- GETFIELDCOPY(Version,' '); /* <Version> */
- if(strcmp(Version,VERSION)) {
- Fatal("CTM-patch is wrong version.");
- if(Verbose>3)
- fprintf(stderr,"Expected \"%s\" got \"%s\".\n",VERSION,p);
- return 1;
- }
-
- GETFIELDCOPY(Name,' '); /* <Name> */
- GETFIELDCOPY(Nbr,' '); /* <Nbr> */
- GETFIELDCOPY(TimeStamp,' '); /* <TimeStamp> */
- GETFIELDCOPY(Prefix,'\n'); /* <Prefix> */
-
- sscanf(Nbr, "%u", &current);
- if (FilterList || ListIt)
- current = 0; /* ignore if -l or if filters are present */
- if(current && current <= applied) {
- if(Verbose > 0)
- fprintf(stderr,"Delta number %u is already applied; ignoring.\n",
- current);
- return Exit_Version;
- }
-
- for(;;) {
- Delete(md5);
- Delete(name);
- Delete(trash);
- cnt = -1;
- /* if a filter list is defined we assume that all pathnames require
- an action opposite to that requested by the first filter in the
- list.
- If no filter is defined, all pathnames are assumed to match. */
- match = (FilterList ? !(FilterList->Action) : CTM_FILTER_ENABLE);
-
- GETFIELD(p,' '); /* CTM_something */
-
- if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') {
- Fatal("Expected CTM keyword.");
- fprintf(stderr,"Got [%s]\n",p);
- return 1;
- }
-
- if(!strcmp(p+3,"_END"))
- break;
-
- for(sp=Syntax;sp->Key;sp++)
- if(!strcmp(p+3,sp->Key))
- goto found;
- Fatal("Expected CTM keyword.");
- fprintf(stderr,"Got [%s]\n",p);
- return 1;
- found:
- if(Verbose > 5)
- fprintf(stderr,"%s ",sp->Key);
- for(i=0;(j = sp->List[i]);i++) {
- if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
- sep = ' ';
- else
- sep = '\n';
-
- if(Verbose > 5)
- fprintf(stderr," %x(%d)",sp->List[i],sep);
-
- switch (j & CTM_F_MASK) {
- case CTM_F_Name: /* XXX check for garbage and .. */
- GETFIELDCOPY(name,sep);
- j = strlen(name);
- if(name[j-1] == '/' && !slashwarn) {
- fprintf(stderr,"Warning: contains trailing slash\n");
- slashwarn++;
- }
- if (name[0] == '/') {
- Fatal("Absolute paths are illegal.");
- Delete(name);
- return Exit_Mess;
- }
- q = name;
- for (;;) {
- if (q[0] == '.' && q[1] == '.')
- if (q[2] == '/' || q[2] == '\0') {
- Fatal("Paths containing '..' are illegal.");
- Delete(name);
- return Exit_Mess;
- }
- if ((q = strchr(q, '/')) == NULL)
- break;
- q++;
- }
-
- /* if we have been asked to `keep' files then skip
- removes; i.e. we don't match these entries at
- all. */
- if (KeepIt &&
- (!strcmp(sp->Key,"DR") || !strcmp(sp->Key,"FR"))) {
- match = CTM_FILTER_DISABLE;
- break;
- }
-
- /* If filter expression have been defined, match the
- path name against the expression list. */
-
- if (FilterList) {
- struct CTM_Filter *filter;
-
- for (filter = FilterList; filter;
- filter = filter->Next) {
- if (0 == regexec(&filter->CompiledRegex, name,
- 0, 0, 0))
- /* if the name matches, adopt the
- action */
- match = filter->Action;
- }
- }
-
- /* Add up the total number of matches */
- total_matches += match;
- break;
- case CTM_F_Uid:
- GETFIELD(p,sep);
- while(*p) {
- if(!isdigit(*p)) {
- Fatal("Non-digit in uid.");
- return 32;
- }
- p++;
- }
- break;
- case CTM_F_Gid:
- GETFIELD(p,sep);
- while(*p) {
- if(!isdigit(*p)) {
- Fatal("Non-digit in gid.");
- return 32;
- }
- p++;
- }
- break;
- case CTM_F_Mode:
- GETFIELD(p,sep);
- while(*p) {
- if(!isdigit(*p)) {
- Fatal("Non-digit in mode.");
- return 32;
- }
- p++;
- }
- break;
- case CTM_F_MD5:
- if(j & CTM_Q_MD5_Chunk) {
- GETFIELDCOPY(md5,sep); /* XXX check for garbage */
- } else if(j & CTM_Q_MD5_Before) {
- GETFIELD(p,sep); /* XXX check for garbage */
- } else if(j & CTM_Q_MD5_After) {
- GETFIELD(p,sep); /* XXX check for garbage */
- } else {
- fprintf(stderr,"List = 0x%x\n",j);
- Fatal("Unqualified MD5.");
- return 32;
- }
- break;
- case CTM_F_Count:
- GETBYTECNT(cnt,sep);
- break;
- case CTM_F_Bytes:
- if(cnt < 0) WRONG
- GETDATA(trash,cnt);
- p = MD5Data(trash,cnt,md5_1);
- if(md5 && strcmp(md5,p)) {
- Fatal("Internal MD5 failed.");
- return Exit_Garbage;
- default:
- fprintf(stderr,"List = 0x%x\n",j);
- Fatal("List had garbage.");
- return Exit_Garbage;
- }
- }
- }
- if(Verbose > 5)
- putc('\n',stderr);
- if(ListIt && match)
- printf("> %s %s\n", sp->Key, name);
- }
-
- Delete(md5);
- Delete(name);
- Delete(trash);
-
- q = MD5End (&ctx,md5_1);
- if(Verbose > 2)
- printf("Expecting Global MD5 <%s>\n",q);
- GETFIELD(p,'\n'); /* <MD5> */
- if(Verbose > 2)
- printf("Reference Global MD5 <%s>\n",p);
- if(strcmp(q,p)) {
- Fatal("MD5 sum doesn't match.");
- fprintf(stderr,"\tI have:<%s>\n",q);
- fprintf(stderr,"\tShould have been:<%s>\n",p);
- return Exit_Garbage;
- }
- if (-1 != getc(fd)) {
- if(!Force) {
- Fatal("Trailing junk in CTM-file. Can Force with -F.");
- return 16;
- }
- }
- if ((Verbose > 1) && (0 == total_matches))
- printf("No matches in \"%s\"\n", FileName);
- return (total_matches ? Exit_OK : Exit_NoMatch);
-}
diff --git a/usr.sbin/ctm/ctm/ctm_pass2.c b/usr.sbin/ctm/ctm/ctm_pass2.c
deleted file mode 100644
index 83dd72c87c26..000000000000
--- a/usr.sbin/ctm/ctm/ctm_pass2.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <[email protected]> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * $FreeBSD$
- *
- */
-
-#include "ctm.h"
-#define BADREAD 32
-
-/*---------------------------------------------------------------------------*/
-/* Pass2 -- Validate the incoming CTM-file.
- */
-
-int
-Pass2(FILE *fd)
-{
- u_char *p,*q,*md5=0;
- MD5_CTX ctx;
- int i,j,sep,cnt,fdesc;
- u_char *trash=0,*name=0;
- struct CTM_Syntax *sp;
- struct stat st;
- int ret = 0;
- int match = 0;
- char md5_1[33];
- struct CTM_Filter *filter;
- FILE *ed = NULL;
- static char *template = NULL;
-
- if(Verbose>3)
- printf("Pass2 -- Checking if CTM-patch will apply\n");
- MD5Init (&ctx);
-
- GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG
- GETFIELD(p,' '); if(strcmp(Version,p)) WRONG
- GETFIELD(p,' '); if(strcmp(Name,p)) WRONG
- /* XXX Lookup name in /etc/ctm,conf, read stuff */
- GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG
- /* XXX Verify that this is the next patch to apply */
- GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG
- GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG
- /* XXX drop or use ? */
-
- for(;;) {
- Delete(trash);
- Delete(name);
- Delete(md5);
- cnt = -1;
-
- /* if a filter list was specified, check file name against
- the filters specified
- if no filter was given operate on all files. */
- match = (FilterList ?
- !(FilterList->Action) : CTM_FILTER_ENABLE);
-
- GETFIELD(p,' ');
-
- if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
-
- if(!strcmp(p+3,"_END"))
- break;
-
- for(sp=Syntax;sp->Key;sp++)
- if(!strcmp(p+3,sp->Key))
- goto found;
- WRONG
- found:
- for(i=0;(j = sp->List[i]);i++) {
- if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
- sep = ' ';
- else
- sep = '\n';
-
- switch (j & CTM_F_MASK) {
- case CTM_F_Name:
- GETNAMECOPY(name,sep,j,0);
- /* If `keep' was specified, we won't remove any files,
- so don't check if the file exists */
- if (KeepIt &&
- (!strcmp(sp->Key,"FR") || !strcmp(sp->Key,"DR"))) {
- match = CTM_FILTER_DISABLE;
- break;
- }
-
- for (filter = FilterList; filter; filter = filter->Next) if (0 == regexec(&filter->CompiledRegex, name,
- 0, 0, 0)) {
- match = filter->Action;
- }
-
- if (CTM_FILTER_DISABLE == match)
- break; /* should ignore this file */
-
- /* XXX Check DR DM rec's for parent-dir */
- if(j & CTM_Q_Name_New) {
- /* XXX Check DR FR rec's for item */
- if(-1 != stat(name,&st)) {
- fprintf(stderr," %s: %s exists.\n",
- sp->Key,name);
- ret |= Exit_Forcible;
- }
- break;
- }
- if(-1 == stat(name,&st)) {
- fprintf(stderr," %s: %s doesn't exist.\n",
- sp->Key,name);
- if (sp->Key[1] == 'R')
- ret |= Exit_Forcible;
- else
- ret |= Exit_NotOK;
- break;
- }
- if (SetTime && getuid() && (getuid() != st.st_uid)) {
- fprintf(stderr,
- " %s: %s not mine, cannot set time.\n",
- sp->Key,name);
- ret |= Exit_NotOK;
- }
- if (j & CTM_Q_Name_Dir) {
- if((st.st_mode & S_IFMT) != S_IFDIR) {
- fprintf(stderr,
- " %s: %s exist, but isn't dir.\n",
- sp->Key,name);
- ret |= Exit_NotOK;
- }
- break;
- }
- if (j & CTM_Q_Name_File) {
- if((st.st_mode & S_IFMT) != S_IFREG) {
- fprintf(stderr,
- " %s: %s exist, but isn't file.\n",
- sp->Key,name);
- ret |= Exit_NotOK;
- }
- break;
- }
- break;
- case CTM_F_Uid:
- case CTM_F_Gid:
- case CTM_F_Mode:
- GETFIELD(p,sep);
- break;
- case CTM_F_MD5:
- if(!name) WRONG
- if(j & CTM_Q_MD5_Before) {
- char *tmp;
- GETFIELD(p,sep);
- if(match && (st.st_mode & S_IFMT) == S_IFREG &&
- (tmp = MD5File(name,md5_1)) != NULL &&
- strcmp(tmp,p)) {
- fprintf(stderr," %s: %s md5 mismatch.\n",
- sp->Key,name);
- GETFIELDCOPY(md5,sep);
- if(md5 != NULL && strcmp(tmp,md5) == 0) {
- fprintf(stderr," %s: %s already applied.\n",
- sp->Key,name);
- match = CTM_FILTER_DISABLE;
- } else if(j & CTM_Q_MD5_Force) {
- if(Force)
- fprintf(stderr," Can and will force.\n");
- else
- fprintf(stderr," Could have forced.\n");
- ret |= Exit_Forcible;
- } else {
- ret |= Exit_NotOK;
- }
- }
- break;
- } else if(j & CTM_Q_MD5_After) {
- if(md5 == NULL) {
- GETFIELDCOPY(md5,sep);
- }
- break;
- }
- /* Unqualified MD5 */
- WRONG
- break;
- case CTM_F_Count:
- GETBYTECNT(cnt,sep);
- break;
- case CTM_F_Bytes:
- if(cnt < 0) WRONG
- GETDATA(trash,cnt);
- if (!match)
- break;
- if (!template) {
- if (asprintf(&template, "%s/CTMclientXXXXXX",
- TmpDir) == -1) {
- fprintf(stderr, " %s: malloc failed.\n",
- sp->Key);
- ret |= Exit_Mess;
- return ret;
- }
- }
- if(!strcmp(sp->Key,"FN")) {
- if ((p = strdup(template)) == NULL) {
- fprintf(stderr, " %s: malloc failed.\n",
- sp->Key);
- ret |= Exit_Mess;
- return ret;
- }
- if ((fdesc = mkstemp(p)) == -1) {
- fprintf(stderr, " %s: mkstemp failed.\n",
- sp->Key);
- ret |= Exit_Mess;
- Free(p);
- return ret;
- }
- if (close(fdesc) == -1) {
- fprintf(stderr, " %s: close failed.\n",
- sp->Key);
- ret |= Exit_Mess;
- unlink(p);
- Free(p);
- return ret;
- }
- j = ctm_edit(trash,cnt,name,p);
- if(j) {
- fprintf(stderr," %s: %s edit returned %d.\n",
- sp->Key,name,j);
- ret |= j;
- unlink(p);
- Free(p);
- return ret;
- } else if(strcmp(md5,MD5File(p,md5_1))) {
- fprintf(stderr," %s: %s edit fails.\n",
- sp->Key,name);
- ret |= Exit_Mess;
- unlink(p);
- Free(p);
- return ret;
- }
- unlink(p);
- Free(p);
- } else if (!strcmp(sp->Key,"FE")) {
- if ((p = strdup(template)) == NULL) {
- fprintf(stderr, " %s: malloc failed.\n",
- sp->Key);
- ret |= Exit_Mess;
- return ret;
- }
- if ((fdesc = mkstemp(p)) == -1) {
- fprintf(stderr, " %s: mkstemp failed.\n",
- sp->Key);
- ret |= Exit_Mess;
- Free(p);
- return ret;
- }
- if (close(fdesc) == -1) {
- fprintf(stderr, " %s: close failed.\n",
- sp->Key);
- ret |= Exit_Mess;
- unlink(p);
- Free(p);
- return ret;
- }
- ed = popen("ed","w");
- if (!ed) {
- WRONG
- }
- fprintf(ed,"e %s\n", name);
- if (cnt != fwrite(trash,1,cnt,ed)) {
- warn("%s", name);
- pclose(ed);
- WRONG
- }
- fprintf(ed,"w %s\n",p);
- if (pclose(ed)) {
- warn("%s", p);
- WRONG
- }
- if(strcmp(md5,MD5File(p,md5_1))) {
- fprintf(stderr,"%s %s MD5 didn't come out right\n",
- sp->Key, name);
- WRONG
- }
- unlink(p);
- Free(p);
- }
-
- break;
- default: WRONG
- }
- }
- }
-
- Delete(trash);
- Delete(name);
- Delete(md5);
-
- q = MD5End (&ctx,md5_1);
- GETFIELD(p,'\n'); /* <MD5> */
- if(strcmp(q,p)) WRONG
- if (-1 != getc(fd)) WRONG
- return ret;
-}
diff --git a/usr.sbin/ctm/ctm/ctm_pass3.c b/usr.sbin/ctm/ctm/ctm_pass3.c
deleted file mode 100644
index e77e8107722d..000000000000
--- a/usr.sbin/ctm/ctm/ctm_pass3.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <[email protected]> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * $FreeBSD$
- *
- */
-
-#include "ctm.h"
-#define BADREAD 32
-
-/*---------------------------------------------------------------------------*/
-/* Pass3 -- Validate the incoming CTM-file.
- */
-
-int
-settime(const char *name, const struct timeval *times)
-{
- if (SetTime)
- if (utimes(name,times)) {
- warn("utimes(): %s", name);
- return -1;
- }
- return 0;
-}
-
-int
-Pass3(FILE *fd)
-{
- u_char *p,*q,buf[BUFSIZ];
- MD5_CTX ctx;
- int i,j,sep,cnt;
- u_char *md5=0,*md5before=0,*trash=0,*name=0,*uid=0,*gid=0,*mode=0;
- struct CTM_Syntax *sp;
- FILE *ed=0;
- struct stat st;
- char md5_1[33];
- int match=0;
- struct timeval times[2];
- struct CTM_Filter *filter = NULL;
- if(Verbose>3)
- printf("Pass3 -- Applying the CTM-patch\n");
- MD5Init (&ctx);
-
- GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG
- GETFIELD(p,' '); if(strcmp(Version,p)) WRONG
- GETFIELD(p,' '); if(strcmp(Name,p)) WRONG
- GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG
- GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG
- GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG
-
- /*
- * This would be cleaner if mktime() worked in UTC rather than
- * local time.
- */
- if (SetTime) {
- struct tm tm;
- char *tz;
- char buf[5];
- int i;
-
-#define SUBSTR(off,len) strncpy(buf, &TimeStamp[off], len), buf[len] = '\0'
-#define WRONGDATE { fprintf(stderr, " %s failed date validation\n",\
- TimeStamp); WRONG}
-
- if (strlen(TimeStamp) != 15 || TimeStamp[14] != 'Z') WRONGDATE
- for (i = 0; i < 14; i++)
- if (!isdigit(TimeStamp[i])) WRONGDATE
-
- tz = getenv("TZ");
- if (setenv("TZ", "UTC", 1) < 0) WRONG
- tzset();
-
- tm.tm_isdst = tm.tm_gmtoff = 0;
-
- SUBSTR(0, 4);
- tm.tm_year = atoi(buf) - 1900;
- SUBSTR(4, 2);
- tm.tm_mon = atoi(buf) - 1;
- if (tm.tm_mon < 0 || tm.tm_mon > 11) WRONGDATE
- SUBSTR(6, 2);
- tm.tm_mday = atoi(buf);
- if (tm.tm_mday < 1 || tm.tm_mday > 31) WRONG;
- SUBSTR(8, 2);
- tm.tm_hour = atoi(buf);
- if (tm.tm_hour > 24) WRONGDATE
- SUBSTR(10, 2);
- tm.tm_min = atoi(buf);
- if (tm.tm_min > 59) WRONGDATE
- SUBSTR(12, 2);
- tm.tm_sec = atoi(buf);
- if (tm.tm_min > 62) WRONGDATE /* allow leap seconds */
-
- times[0].tv_sec = times[1].tv_sec = mktime(&tm);
- if (times[0].tv_sec == -1) WRONGDATE
- times[0].tv_usec = times[1].tv_usec = 0;
-
- if (tz) {
- if (setenv("TZ", tz, 1) < 0) WRONGDATE
- } else {
- unsetenv("TZ");
- }
- }
-
- for(;;) {
- Delete(md5);
- Delete(uid);
- Delete(gid);
- Delete(mode);
- Delete(md5before);
- Delete(trash);
- Delete(name);
- cnt = -1;
-
- GETFIELD(p,' ');
-
- if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
-
- if(!strcmp(p+3,"_END"))
- break;
-
- for(sp=Syntax;sp->Key;sp++)
- if(!strcmp(p+3,sp->Key))
- goto found;
- WRONG
- found:
- for(i=0;(j = sp->List[i]);i++) {
- if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
- sep = ' ';
- else
- sep = '\n';
-
- switch (j & CTM_F_MASK) {
- case CTM_F_Name: GETNAMECOPY(name,sep,j, Verbose); break;
- case CTM_F_Uid: GETFIELDCOPY(uid,sep); break;
- case CTM_F_Gid: GETFIELDCOPY(gid,sep); break;
- case CTM_F_Mode: GETFIELDCOPY(mode,sep); break;
- case CTM_F_MD5:
- if(j & CTM_Q_MD5_Before)
- GETFIELDCOPY(md5before,sep);
- else
- GETFIELDCOPY(md5,sep);
- break;
- case CTM_F_Count: GETBYTECNT(cnt,sep); break;
- case CTM_F_Bytes: GETDATA(trash,cnt); break;
- default: WRONG
- }
- }
- /* XXX This should go away. Disallow trailing '/' */
- j = strlen(name)-1;
- if(name[j] == '/') name[j] = '\0';
-
- /*
- * If a filter list is specified, run thru the filter list and
- * match `name' against filters. If the name matches, set the
- * required action to that specified in the filter.
- * The default action if no filterlist is given is to match
- * everything.
- */
-
- match = (FilterList ? !(FilterList->Action) : CTM_FILTER_ENABLE);
- for (filter = FilterList; filter; filter = filter->Next) {
- if (0 == regexec(&filter->CompiledRegex, name,
- 0, 0, 0)) {
- match = filter->Action;
- }
- }
-
- if (CTM_FILTER_DISABLE == match) /* skip file if disabled */
- continue;
-
- if (Verbose > 0)
- fprintf(stderr,"> %s %s\n",sp->Key,name);
- if(!strcmp(sp->Key,"FM") || !strcmp(sp->Key, "FS")) {
- i = open(name,O_WRONLY|O_CREAT|O_TRUNC,0666);
- if(i < 0) {
- warn("%s", name);
- WRONG
- }
- if(cnt != write(i,trash,cnt)) {
- warn("%s", name);
- WRONG
- }
- close(i);
- if(strcmp(md5,MD5File(name,md5_1))) {
- fprintf(stderr," %s %s MD5 didn't come out right\n",
- sp->Key,name);
- WRONG
- }
- if (settime(name,times)) WRONG
- continue;
- }
- if(!strcmp(sp->Key,"FE")) {
- ed = popen("ed","w");
- if(!ed) {
- WRONG
- }
- fprintf(ed,"e %s\n",name);
- if(cnt != fwrite(trash,1,cnt,ed)) {
- warn("%s", name);
- pclose(ed);
- WRONG
- }
- fprintf(ed,"w %s\n",name);
- if(pclose(ed)) {
- warn("ed");
- WRONG
- }
- if(strcmp(md5,MD5File(name,md5_1))) {
- fprintf(stderr," %s %s MD5 didn't come out right\n",
- sp->Key,name);
- WRONG
- }
- if (settime(name,times)) WRONG
- continue;
- }
- if(!strcmp(sp->Key,"FN")) {
- strcpy(buf,name);
- strcat(buf,TMPSUFF);
- i = ctm_edit(trash,cnt,name,buf);
- if(i) {
- fprintf(stderr," %s %s Edit failed with code %d.\n",
- sp->Key,name,i);
- WRONG
- }
- if(strcmp(md5,MD5File(buf,md5_1))) {
- fprintf(stderr," %s %s Edit failed MD5 check.\n",
- sp->Key,name);
- WRONG
- }
- if (rename(buf,name) == -1)
- WRONG
- if (settime(name,times)) WRONG
- continue;
- }
- if(!strcmp(sp->Key,"DM")) {
- if(0 > mkdir(name,0777)) {
- sprintf(buf,"mkdir -p %s",name);
- system(buf);
- }
- if(0 > stat(name,&st) || ((st.st_mode & S_IFMT) != S_IFDIR)) {
- fprintf(stderr,"<%s> mkdir failed\n",name);
- WRONG
- }
- if (settime(name,times)) WRONG
- continue;
- }
- if(!strcmp(sp->Key,"FR")) {
- if (KeepIt) {
- if (Verbose > 1)
- printf("<%s> not removed\n", name);
- }
- else if (0 != unlink(name)) {
- fprintf(stderr,"<%s> unlink failed\n",name);
- if (!Force)
- WRONG
- }
- continue;
- }
- if(!strcmp(sp->Key,"DR")) {
- /*
- * We cannot use rmdir() because we do not get the directories
- * in '-depth' order (cvs-cur.0018.gz for examples)
- */
- if (KeepIt) {
- if (Verbose > 1) {
- printf("<%s> not removed\n", name);
- }
- } else {
- sprintf(buf,"rm -rf %s",name);
- system(buf);
- }
- continue;
- }
- WRONG
- }
-
- Delete(md5);
- Delete(uid);
- Delete(gid);
- Delete(mode);
- Delete(md5before);
- Delete(trash);
- Delete(name);
-
- q = MD5End (&ctx,md5_1);
- GETFIELD(p,'\n');
- if(strcmp(q,p)) WRONG
- if (-1 != getc(fd)) WRONG
- return 0;
-}
diff --git a/usr.sbin/ctm/ctm/ctm_passb.c b/usr.sbin/ctm/ctm/ctm_passb.c
deleted file mode 100644
index 3f32cb238d72..000000000000
--- a/usr.sbin/ctm/ctm/ctm_passb.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <[email protected]> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Joseph Koshy
- * ----------------------------------------------------------------------------
- *
- * $FreeBSD$
- *
- */
-
-#include "ctm.h"
-#define BADREAD 32
-
-/*---------------------------------------------------------------------------*/
-/* PassB -- Backup modified files.
- */
-
-int
-PassB(FILE *fd)
-{
- u_char *p,*q;
- MD5_CTX ctx;
- int i,j,sep,cnt;
- u_char *md5=0,*md5before=0,*trash=0,*name=0,*uid=0,*gid=0,*mode=0;
- struct CTM_Syntax *sp;
- FILE *b = 0; /* backup command */
- u_char buf[BUFSIZ];
- char md5_1[33];
- int ret = 0;
- int match = 0;
- struct CTM_Filter *filter = NULL;
-
- if(Verbose>3)
- printf("PassB -- Backing up files which would be changed.\n");
-
- MD5Init (&ctx);
- snprintf(buf, sizeof(buf), fmtcheck(TarCmd, TARCMD), BackupFile);
- b=popen(buf, "w");
- if(!b) { warn("%s", buf); return Exit_Garbage; }
-
- GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG
- GETFIELD(p,' '); if(strcmp(Version,p)) WRONG
- GETFIELD(p,' '); if(strcmp(Name,p)) WRONG
- GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG
- GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG
- GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG
-
- for(;;) {
- Delete(md5);
- Delete(uid);
- Delete(gid);
- Delete(mode);
- Delete(md5before);
- Delete(trash);
- Delete(name);
- cnt = -1;
-
- GETFIELD(p,' ');
-
- if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
-
- if(!strcmp(p+3,"_END"))
- break;
-
- for(sp=Syntax;sp->Key;sp++)
- if(!strcmp(p+3,sp->Key))
- goto found;
- WRONG
- found:
- for(i=0;(j = sp->List[i]);i++) {
- if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
- sep = ' ';
- else
- sep = '\n';
-
- switch (j & CTM_F_MASK) {
- case CTM_F_Name: GETNAMECOPY(name,sep,j, Verbose); break;
- case CTM_F_Uid: GETFIELDCOPY(uid,sep); break;
- case CTM_F_Gid: GETFIELDCOPY(gid,sep); break;
- case CTM_F_Mode: GETFIELDCOPY(mode,sep); break;
- case CTM_F_MD5:
- if(j & CTM_Q_MD5_Before)
- GETFIELDCOPY(md5before,sep);
- else
- GETFIELDCOPY(md5,sep);
- break;
- case CTM_F_Count: GETBYTECNT(cnt,sep); break;
- case CTM_F_Bytes: GETDATA(trash,cnt); break;
- default: WRONG
- }
- }
- /* XXX This should go away. Disallow trailing '/' */
- j = strlen(name)-1;
- if(name[j] == '/') name[j] = '\0';
-
- if (KeepIt &&
- (!strcmp(sp->Key,"DR") || !strcmp(sp->Key,"FR")))
- continue;
-
- /* match the name against the elements of the filter list. The
- action associated with the last matched filter determines whether
- this file should be ignored or backed up. */
- match = (FilterList ? !(FilterList->Action) : CTM_FILTER_ENABLE);
- for (filter = FilterList; filter; filter = filter->Next) {
- if (0 == regexec(&filter->CompiledRegex, name, 0, 0, 0))
- match = filter->Action;
- }
-
- if (CTM_FILTER_DISABLE == match)
- continue;
-
- if (!strcmp(sp->Key,"FS") || !strcmp(sp->Key,"FN") ||
- !strcmp(sp->Key,"AS") || !strcmp(sp->Key,"DR") ||
- !strcmp(sp->Key,"FR")) {
- /* send name to the archiver for a backup */
- cnt = strlen(name);
- if (cnt != fwrite(name,1,cnt,b) || EOF == fputc('\n',b)) {
- warn("%s", name);
- pclose(b);
- WRONG;
- }
- }
- }
-
- ret = pclose(b);
-
- Delete(md5);
- Delete(uid);
- Delete(gid);
- Delete(mode);
- Delete(md5before);
- Delete(trash);
- Delete(name);
-
- q = MD5End (&ctx,md5_1);
- GETFIELD(p,'\n'); /* <MD5> */
- if(strcmp(q,p)) WRONG
- if (-1 != getc(fd)) WRONG
- return ret;
-}
diff --git a/usr.sbin/ctm/ctm/ctm_syntax.c b/usr.sbin/ctm/ctm/ctm_syntax.c
deleted file mode 100644
index 968e653e6465..000000000000
--- a/usr.sbin/ctm/ctm/ctm_syntax.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <[email protected]> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * $FreeBSD$
- *
- */
-
-#include "ctm.h"
-
-/* The fields... */
-#define Name CTM_F_Name
-#define Uid CTM_F_Uid
-#define Gid CTM_F_Gid
-#define Mode CTM_F_Mode
-#define MD5 CTM_F_MD5
-#define Count CTM_F_Count
-#define Bytes CTM_F_Bytes
-
-/* The qualifiers... */
-#define File CTM_Q_Name_File
-#define Dir CTM_Q_Name_Dir
-#define New CTM_Q_Name_New
-#define Subst CTM_Q_Name_Subst
-#define After CTM_Q_MD5_After
-#define Before CTM_Q_MD5_Before
-#define Chunk CTM_Q_MD5_Chunk
-#define Force CTM_Q_MD5_Force
-
-static int ctmFM[] = /* File Make */
- { Name|File|New|Subst, Uid, Gid, Mode,
- MD5|After|Chunk, Count, Bytes,0 };
-
-static int ctmFS[] = /* File Substitute */
- { Name|File|Subst, Uid, Gid, Mode,
- MD5|Before|Force, MD5|After|Chunk, Count, Bytes,0 };
-
-static int ctmFE[] = /* File Edit */
- { Name|File|Subst, Uid, Gid, Mode,
- MD5|Before, MD5|After, Count, Bytes,0 };
-
-static int ctmFR[] = /* File Remove */
- { Name|File|Subst, MD5|Before, 0 };
-
-static int ctmAS[] = /* Attribute Substitute */
- { Name|Subst, Uid, Gid, Mode, 0 };
-
-static int ctmDM[] = /* Directory Make */
- { Name|Dir|New , Uid, Gid, Mode, 0 };
-
-static int ctmDR[] = /* Directory Remove */
- { Name|Dir, 0 };
-
-struct CTM_Syntax Syntax[] = {
- { "FM", ctmFM },
- { "FS", ctmFS },
- { "FE", ctmFE },
- { "FN", ctmFE },
- { "FR", ctmFR },
- { "AS", ctmAS },
- { "DM", ctmDM },
- { "DR", ctmDR },
- { 0, 0} };
diff --git a/usr.sbin/ctm/ctm_dequeue/Makefile b/usr.sbin/ctm/ctm_dequeue/Makefile
deleted file mode 100644
index cbc7f0c5257b..000000000000
--- a/usr.sbin/ctm/ctm_dequeue/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${.CURDIR:H}/ctm_rmail
-
-PROG= ctm_dequeue
-MAN=
-SRCS= ctm_dequeue.c error.c
-
-CFLAGS+= -I${.CURDIR:H}/ctm_rmail
-
-WARNS?= 1
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/ctm/ctm_dequeue/Makefile.depend b/usr.sbin/ctm/ctm_dequeue/Makefile.depend
deleted file mode 100644
index 6cfaab1c3644..000000000000
--- a/usr.sbin/ctm/ctm_dequeue/Makefile.depend
+++ /dev/null
@@ -1,17 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/ctm/ctm_dequeue/ctm_dequeue.c b/usr.sbin/ctm/ctm_dequeue/ctm_dequeue.c
deleted file mode 100644
index 51665b849d38..000000000000
--- a/usr.sbin/ctm/ctm_dequeue/ctm_dequeue.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 1996, Gary J. Palmer
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer,
- * verbatim and that no modifications are made prior to this
- * point in the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * ctm_dequeue: Dequeue queued delta pieces and mail them.
- *
- * The pieces have already been packaged up as mail messages by ctm_smail,
- * and will be simply passed to sendmail in alphabetical order.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <fts.h>
-#include <limits.h>
-#include <errno.h>
-#include <paths.h>
-#include "error.h"
-#include "options.h"
-
-#define DEFAULT_NUM 1 /* Default number of pieces mailed per run. */
-
-int fts_sort(const FTSENT * const *, const FTSENT * const *);
-int run_sendmail(int ifd);
-
-int
-main(int argc, char **argv)
-{
- char *log_file = NULL;
- char *queue_dir = NULL;
- char *list[2];
- int num_to_send = DEFAULT_NUM, chunk;
- int fd;
- FTS *fts;
- FTSENT *ftsent;
- int piece, npieces;
- char filename[PATH_MAX];
-
- err_prog_name(argv[0]);
-
- OPTIONS("[-l log] [-n num] queuedir")
- NUMBER('n', num_to_send)
- STRING('l', log_file)
- ENDOPTS
-
- if (argc != 2)
- usage();
-
- if (log_file)
- err_set_log(log_file);
-
- queue_dir = argv[1];
- list[0] = queue_dir;
- list[1] = NULL;
-
- fts = fts_open(list, FTS_PHYSICAL|FTS_COMFOLLOW, fts_sort);
- if (fts == NULL)
- {
- err("fts failed on `%s'", queue_dir);
- exit(1);
- }
-
- ftsent = fts_read(fts);
- if (ftsent == NULL || ftsent->fts_info != FTS_D)
- {
- err("not a directory: %s", queue_dir);
- exit(1);
- }
-
- ftsent = fts_children(fts, 0);
- if (ftsent == NULL && errno)
- {
- err("*ftschildren failed");
- exit(1);
- }
-
- for (chunk = 1; ftsent != NULL; ftsent = ftsent->fts_link)
- {
- /*
- * Skip non-files and ctm_smail tmp files (ones starting with `.')
- */
- if (ftsent->fts_info != FTS_F || ftsent->fts_name[0] == '.')
- continue;
-
- snprintf(filename, sizeof(filename), "%s/%s", queue_dir,
- ftsent->fts_name);
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- {
- err("*open: %s", filename);
- exit(1);
- }
-
- if (run_sendmail(fd))
- exit(1);
-
- close(fd);
-
- if (unlink(filename) < 0)
- {
- err("*unlink: %s", filename);
- exit(1);
- }
-
- /*
- * Deduce the delta, piece number, and number of pieces from
- * the name of the file in the queue. Ideally, we should be
- * able to get the mail alias name too.
- *
- * NOTE: This depends intimately on the queue name used in ctm_smail.
- */
- npieces = atoi(&ftsent->fts_name[ftsent->fts_namelen-3]);
- piece = atoi(&ftsent->fts_name[ftsent->fts_namelen-7]);
- err("%.*s %d/%d sent", (int)(ftsent->fts_namelen-8), ftsent->fts_name,
- piece, npieces);
-
- if (chunk++ == num_to_send)
- break;
- }
-
- fts_close(fts);
-
- return(0);
-}
-
-int
-fts_sort(const FTSENT * const * a, const FTSENT * const * b)
-{
- if ((*a)->fts_info != FTS_F)
- return(0);
- if ((*a)->fts_info != FTS_F)
- return(0);
-
- return (strcmp((*a)->fts_name, (*b)->fts_name));
-}
-
-/*
- * Run sendmail with the given file descriptor as standard input.
- * Sendmail will decode the destination from the message contents.
- * Returns 0 on success, 1 on failure.
- */
-int
-run_sendmail(int ifd)
-{
- pid_t child, pid;
- int status;
-
- switch (child = fork())
- {
- case -1:
- err("*fork");
- return(1);
-
- case 0: /* Child */
- dup2(ifd, 0);
- execl(_PATH_SENDMAIL, _PATH_SENDMAIL, "-odq", "-t", (char *)NULL);
- err("*exec: %s", _PATH_SENDMAIL);
- _exit(1);
-
- default: /* Parent */
- while ((pid = wait(&status)) != child)
- {
- if (pid == -1 && errno != EINTR)
- {
- err("*wait");
- return(1);
- }
- }
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- {
- err("sendmail failed");
- return(1);
- }
- }
-
- return(0);
-}
diff --git a/usr.sbin/ctm/ctm_rmail/Makefile b/usr.sbin/ctm/ctm_rmail/Makefile
deleted file mode 100644
index 1278ab46fa08..000000000000
--- a/usr.sbin/ctm/ctm_rmail/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# $FreeBSD$
-
-PROG= ctm_rmail
-MLINKS= ctm_rmail.1 ctm_smail.1 \
- ctm_rmail.1 ctm_dequeue.1
-SRCS= ctm_rmail.c error.c
-
-WARNS?= 2
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/ctm/ctm_rmail/Makefile.depend b/usr.sbin/ctm/ctm_rmail/Makefile.depend
deleted file mode 100644
index 6cfaab1c3644..000000000000
--- a/usr.sbin/ctm/ctm_rmail/Makefile.depend
+++ /dev/null
@@ -1,17 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/ctm/ctm_rmail/ctm_rmail.1 b/usr.sbin/ctm/ctm_rmail/ctm_rmail.1
deleted file mode 100644
index 232f646529f8..000000000000
--- a/usr.sbin/ctm/ctm_rmail/ctm_rmail.1
+++ /dev/null
@@ -1,510 +0,0 @@
-.\" NOTICE: This is free documentation. I hope you get some use from these
-.\" words. In return you should think about all the nice people who sweat
-.\" blood to document their free software. Maybe you should write some
-.\" documentation and give it away. Maybe with a free program attached!
-.\"
-.\" Author: Stephen McKay
-.\"
-.\" $FreeBSD$
-.\"
-.Dd January 24, 1995
-.Dt CTM_MAIL 1
-.Os
-.Sh NAME
-.Nm ctm_smail ,
-.Nm ctm_dequeue ,
-.Nm ctm_rmail
-.Nd send and receive
-.Xr ctm 1
-deltas via mail
-.Sh SYNOPSIS
-.Nm ctm_smail
-.Op Fl l Ar log
-.Op Fl m Ar maxmsgsize
-.Op Fl c Ar maxctmsize
-.Op Fl q Ar queue-dir
-.Ar ctm-delta
-.Ar mail-alias
-.Nm ctm_dequeue
-.Op Fl l Ar log
-.Op Fl n Ar numchunks
-.Ar queue-dir
-.Nm ctm_rmail
-.Op Fl Dfuv
-.Op Fl l Ar log
-.Op Fl p Ar piecedir
-.Op Fl d Ar deltadir
-.Op Fl b Ar basedir
-.Op Ar
-.Sh DESCRIPTION
-In conjunction with the
-.Xr ctm 1
-command,
-.Nm ctm_smail ,
-.Nm ctm_dequeue
-and
-.Nm ctm_rmail
-are used to distribute changes to a source tree via email.
-The
-.Nm ctm_smail
-utility is given a compressed
-.Xr ctm
-delta, and a mailing list to send it to.
-It splits the delta into manageable
-pieces, encodes them as mail messages and sends them to the mailing list
-(optionally queued to spread the mail load).
-Each recipient uses
-.Nm ctm_rmail
-(either manually or automatically) to decode and reassemble the delta, and
-optionally call
-.Xr ctm
-to apply it to the source tree.
-At the moment,
-several source trees are distributed, and by several sites.
-These include
-the
-.Fx Ns -current
-source and CVS trees, distributed by
-.Li freefall.FreeBSD.org .
-.Pp
-Command line arguments for
-.Nm ctm_smail :
-.Bl -tag -width indent
-.It Fl l Ar log
-Instead of appearing on
-.Em stderr ,
-error diagnostics and informational messages (other than command line errors)
-are time stamped and written to the file
-.Em log .
-.It Fl m Ar maxmsgsize
-Limit the maximum size mail message that
-.Nm ctm_smail
-is allowed to send.
-It is approximate since mail headers and other niceties
-are not counted in this limit.
-If not specified, it will default to 64000
-bytes, leaving room for 1535 bytes of headers before the rumoured 64k mail
-limit.
-.It Fl c Ar maxctmsize
-Limit the maximum size delta that will be sent.
-Deltas bigger that this
-limit will cause an apology mail message to be sent to the mailing list.
-This is to prevent massive changes overwhelming users' mail boxes.
-Note that
-this is the size before encoding.
-Encoding causes a 4/3 size increase before
-mail headers are added.
-If not specified, there is no limit.
-.It Fl q Ar queue-dir
-Instead of mailing the delta pieces now, store them in the given directory
-to be mailed later using
-.Nm ctm_dequeue .
-This feature allows the mailing of large deltas to be spread out over
-hours or even days to limit the impact on recipients with limited network
-bandwidth or small mail spool areas.
-.El
-.Pp
-.Ar ctm-delta
-is the delta to be sent, and
-.Ar mail-alias
-is the mailing list to send the delta to.
-The mail messages are sent using
-.Xr sendmail 8 .
-.Pp
-Command line arguments for
-.Nm ctm_dequeue :
-.Bl -tag -width indent
-.It Fl l Ar log
-Instead of appearing on
-.Em stderr ,
-error diagnostics and informational messages (other than command line errors)
-are time stamped and written to the file
-.Em log .
-.It Fl n Ar numchunks
-Limit the number of mail messages that
-.Nm ctm_dequeue
-will send per run.
-By default,
-.Nm ctm_dequeue
-will send one mail message per run.
-.El
-.Pp
-.Ar queuedir
-is the directory containing the mail messages stored by
-.Nm ctm_smail .
-Up to
-.Ar numchunks
-mail messages will be sent in each run.
-The recipient mailing list is already
-encoded in the queued files.
-.Pp
-It is safe to run
-.Nm ctm_dequeue
-while
-.Nm ctm_smail
-is adding entries to the queue, or even to run
-.Nm ctm_smail
-multiple times concurrently, but a separate queue directory should be used
-for each tree being distributed.
-This is because entries are served in
-alphabetical order, and one tree will be unfairly serviced before any others,
-based on the delta names, not delta creation times.
-.Pp
-Command line arguments for
-.Nm ctm_rmail :
-.Bl -tag -width indent
-.It Fl l Ar log
-Instead of appearing on
-.Em stderr ,
-error diagnostics and informational messages (other than command line errors)
-are time stamped and written to the file
-.Em log .
-.It Fl p Ar piecedir
-Collect pieces of deltas in this directory.
-Each piece corresponds to a
-single mail message.
-Pieces are removed when complete deltas are built.
-If this flag is not given, no input files will be read, but completed
-deltas may still be applied with
-.Xr ctm
-if the
-.Fl b
-flag is given.
-.It Fl d Ar deltadir
-Collect completed deltas in this directory.
-Deltas are built from one or
-more pieces when all pieces are present.
-.It Fl b Ar basedir
-Apply any completed deltas to this source tree.
-If this flag is not given,
-deltas will be stored, but not applied.
-The user may then apply the deltas
-manually, or by using
-.Nm ctm_rmail
-without the
-.Fl p
-flag.
-Deltas will not be applied if they do not match the
-.Li .ctm_status
-file in
-.Ar basedir
-(or if
-.Li .ctm_status
-does not exist).
-.It Fl D
-Delete deltas after successful application by
-.Xr ctm .
-It is probably a good idea to avoid this flag (and keep all the deltas) as
-.Xr ctm
-has the ability to recover small groups of files from a full set of deltas.
-.It Fl f
-Fork and execute in the background while applying deltas with
-.Xr ctm .
-This is useful when automatically invoking
-.Nm ctm_rmail
-from
-.Xr sendmail
-because
-.Xr ctm
-can take a very long time to complete, causing other people's mail to
-be delayed, and can in theory cause spurious
-mail retransmission due to the remote
-.Xr sendmail
-timing out, or even termination of
-.Nm ctm_rmail
-by mail filters such as
-.Xr "MH's"
-.Xr slocal .
-Do not worry about zillions of background
-.Xr ctm
-processes loading your machine, since locking is used to prevent more than one
-.Xr ctm
-invocation at a time.
-.It Fl u
-Pass the
-.Fl u
-flag to the
-.Xr ctm
-command when applying the complete deltas, causing it to set the modification
-time of created and modified files to the CTM delta creation time.
-.It Fl v
-Pass the
-.Fl v
-flag to the
-.Xr ctm
-command when applying the complete deltas, causing a more informative
-output.
-All
-.Xr ctm
-output appears in the
-.Nm ctm_rmail
-log file.
-.El
-.Pp
-The file arguments (or
-.Em stdin ,
-if there are none) are scanned for delta pieces.
-Multiple delta pieces
-can be read from a single file, so an entire maildrop can be scanned
-and processed with a single command.
-.Pp
-It is safe to invoke
-.Nm ctm_rmail
-multiple times concurrently (with different input files),
-as might happen when
-.Xr sendmail
-is delivering mail asynchronously.
-This is because locking is used to
-keep things orderly.
-.Sh FILE FORMAT
-Following are the important parts of an actual (very small) delta piece:
-.Bd -literal
-From: owner-src-cur
-To: src-cur
-Subject: ctm-mail src-cur.0003.gz 1/4
-
-CTM_MAIL BEGIN src-cur.0003.gz 1 4
-H4sIAAAAAAACA3VU72/bNhD9bP0VByQoEiyRSZEUSQP9kKTeYCR2gDTdsGFAwB/HRogtG5K8NCj6
-v4+UZSdtUQh6Rz0eee/xaF/dzx8up3/MFlDkBNrGnbttAwyo1pxoRgoiBNX/QJ5d3c9/X8DcPGGo
-lggkPiXngE4W1gUjKPJCYyk5MZRbIqmNW/ASglIFcdwIzTUxaAqhnCPcBqloKEkJVNDMF0Azk+Bo
-dDzzk0Ods/+A5gXv9YyJHjMCtJwQNeESNma7hOmXDRxn
-CTM_MAIL END 61065
-.Ed
-.Pp
-The subject of the message always begins with
-.Dq ctm-mail
-followed by the name of the delta, which piece this is, and how many total
-pieces there are.
-The data are bracketed by
-.Dq CTM_MAIL BEGIN
-and
-.Dq CTM_MAIL END
-lines, duplicating the information in the subject line, plus a simple checksum.
-.Pp
-If the delta exceeds
-.Ar maxctmsize ,
-then a message like this will be received instead:
-.Bd -literal
-From: owner-src-cur
-To: src-cur
-Subject: ctm-notice src-cur.0999.gz
-
-src-cur.0999.gz is 792843 bytes. The limit is 300000 bytes.
-
-You can retrieve this delta via ftp.
-.Ed
-.Pp
-You are then on your own!
-.Sh ENVIRONMENT
-If deltas are to be applied then
-.Xr ctm 1
-and
-.Xr gunzip 1
-must be in your
-.Ev PATH .
-.Sh FILES
-.Bl -tag -width indent
-.It Pa QUEUEDIR/*
-Pieces of deltas encoded as mail messages waiting to be sent to the
-mailing list.
-.It Pa PIECEDIR/*
-Pieces of deltas waiting for the rest to arrive.
-.It Pa DELTADIR/*
-Completed deltas.
-.It Pa BASEDIR/.ctm_status
-File containing the name and number of the next delta to be applied to this
-source tree.
-.El
-.Sh EXIT STATUS
-The
-.Nm ctm_smail ,
-.Nm ctm_dequeue
-and
-.Nm ctm_rmail
-utilities return exit status 0 for success, and 1 for various failures.
-The
-.Nm ctm_rmail
-utility is expected to be called from a mail transfer program, and thus signals
-failure only when the input mail message should be bounced (preferably into
-your regular maildrop, not back to the sender).
-In short, failure to
-apply a completed delta with
-.Xr ctm
-is not considered an error important enough to bounce the mail, and
-.Nm ctm_rmail
-returns an exit status of 0.
-.Sh EXAMPLES
-To send delta 32 of
-.Em src-cur
-to a group of wonderful code hackers known to
-.Xr sendmail
-as
-.Em src-guys ,
-limiting the mail size to roughly 60000 bytes, you could use:
-.Bd -literal -offset indent
-ctm_smail -m 60000 /wherever/it/is/src-cur.0032.gz src-guys
-.Ed
-.Pp
-To decode every
-.Nm ctm-mail
-message in your mailbox, assemble them into complete deltas, then apply
-any deltas built or lying around, you could use:
-.Bd -literal -offset indent
-ctm_rmail -p ~/pieces -d ~/deltas -b /usr/ctm-src-cur $MAIL
-.Ed
-.Pp
-(Note that no messages are deleted by
-.Nm ctm_rmail .
-Any mail reader could be used for that purpose.)
-.Pp
-To create a mail alias called
-.Em receiver-dude
-that will automatically decode and assemble deltas, but not apply them,
-you could put the following lines in your
-.Pa /etc/mail/aliases
-file (assuming the
-.Pa /ctm/tmp
-and
-.Pa /ctm/deltas
-directories and
-.Pa /ctm/log
-file are writable by user
-.Em daemon
-or group
-.Em wheel ) :
-.Bd -literal -offset indent
-receiver-dude: "|ctm_rmail -p /ctm/tmp -d /ctm/deltas -l /ctm/log"
-owner-receiver-dude: [email protected]
-.Ed
-.Pp
-The second line will catch failures and drop them into your regular mailbox,
-or wherever else you like.
-.Pp
-To apply all the deltas collected, and delete those applied, you could use:
-.Bd -literal -offset indent
-ctm_rmail -D -d /ctm/deltas -b /ctm/src-cur -l /ctm/apply.log
-.Ed
-.Pp
-For maximum flexibility, consider this excerpt from a
-.Xr procmail
-script:
-.Bd -literal -offset indent
-PATH=$HOME/bin:$PATH
-
-:0 w
-* ^Subject: ctm-mail cvs-cur
-| ctm_incoming
-.Ed
-.Pp
-together with the
-shell script
-.Pa ~/bin/ctm_incoming :
-.Bd -literal -offset indent
-#! /bin/sh
-PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin"
-export PATH
-
-cd $HOME/ctm && ctm_rmail -f -p pieces -d deltas -l log -b /ctm
-.Ed
-.Pp
-which will deposit all
-.Xr ctm
-deltas in
-.Pa ~/ctm/deltas ,
-apply them to the tree in
-.Pa /ctm ,
-and drop any failures into your regular mail box.
-Note the
-.Ev PATH
-manipulation in
-.Pa ctm_incoming
-which allows
-.Nm ctm_rmail
-to execute
-.Xr ctm 1
-on the
-.Pq non- Ns Fx
-machine that this example was taken from.
-.Sh SECURITY
-On its own, CTM is an insecure protocol
-- there is no authentication performed that the
-changes applied to the source code were sent by a
-trusted party, and so care should be taken if the
-CTM deltas are obtained via an unauthenticated
-medium such as regular email.
-It is a relatively simple matter for an attacker
-to forge a CTM delta to replace or precede the
-legitimate one and insert malicious code into your
-source tree.
-If the legitimate delta is somehow prevented from
-arriving, this will go unnoticed until a later
-delta attempts to touch the same file, at which
-point the MD5 checksum will fail.
-.Pp
-To remedy this insecurity, CTM delta pieces generated by
-FreeBSD.org are cryptographically signed in a
-format compatible with the GNU Privacy Guard
-utility, available in /usr/ports/security/gpg, and
-the Pretty Good Privacy v5 utility,
-/usr/ports/security/pgp5.
-The relevant public key can be obtained by
-fingering [email protected].
-.Pp
-CTM deltas which are thus signed cannot be
-undetectably altered by an attacker.
-Therefore it is recommended that you make use of
-GPG or PGP5 to verify the signatures if you
-receive your CTM deltas via email.
-.Sh DIAGNOSTICS
-In normal operation,
-.Nm ctm_smail
-will report messages like:
-.Bd -literal -offset indent
-ctm_smail: src-cur.0250.gz 1/2 sent to src-guys
-.Ed
-.Pp
-or, if queueing,
-.Bd -literal -offset indent
-ctm_smail: src-cur.0250.gz 1/2 queued for src-guys
-.Ed
-.Pp
-The
-.Nm ctm_dequeue
-utility will report messages like:
-.Bd -literal -offset indent
-ctm_dequeue: src-cur.0250.gz 1/2 sent
-.Ed
-.Pp
-The
-.Nm ctm_rmail
-utility will report messages like:
-.Bd -literal -offset indent
-ctm_rmail: src-cur.0250.gz 1/2 stored
-ctm_rmail: src-cur.0250.gz 2/2 stored
-ctm_rmail: src-cur.0250.gz complete
-.Ed
-.Pp
-If any of the input files do not contain a valid delta piece,
-.Nm ctm_rmail
-will report:
-.Bd -literal -offset indent
-ctm_rmail: message contains no delta
-.Ed
-.Pp
-and return an exit status of 1.
-You can use this to redirect wayward messages
-back into your real mailbox if your mail filter goes wonky.
-.Pp
-These messages go to
-.Em stderr
-or to the log file.
-Messages from
-.Xr ctm 1
-turn up here too.
-Error messages should be self explanatory.
-.Sh SEE ALSO
-.Xr ctm 1 ,
-.Xr ctm 5
-.\" .Sh HISTORY
-.Sh AUTHORS
-.An Stephen McKay Aq Mt [email protected]
diff --git a/usr.sbin/ctm/ctm_rmail/ctm_rmail.c b/usr.sbin/ctm/ctm_rmail/ctm_rmail.c
deleted file mode 100644
index a46a58aa8734..000000000000
--- a/usr.sbin/ctm/ctm_rmail/ctm_rmail.c
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * Accept one (or more) ASCII encoded chunks that together make a compressed
- * CTM delta. Decode them and reconstruct the deltas. Any completed
- * deltas may be passed to ctm for unpacking.
- *
- * Author: Stephen McKay
- *
- * NOTICE: This is free software. I hope you get some use from this program.
- * In return you should think about all the nice people who give away software.
- * Maybe you should write some free software too.
- *
- * $FreeBSD$
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <limits.h>
-#include "error.h"
-#include "options.h"
-
-#define CTM_STATUS ".ctm_status"
-
-char *piece_dir = NULL; /* Where to store pieces of deltas. */
-char *delta_dir = NULL; /* Where to store completed deltas. */
-char *base_dir = NULL; /* The tree to apply deltas to. */
-int delete_after = 0; /* Delete deltas after ctm applies them. */
-int apply_verbose = 0; /* Run with '-v' */
-int set_time = 0; /* Set the time of the files that is changed. */
-int mask = 0; /* The current umask */
-
-void apply_complete(void);
-int read_piece(char *input_file);
-int combine_if_complete(char *delta, int pce, int npieces);
-int combine(char *delta, int npieces, char *dname, char *pname, char *tname);
-int decode_line(char *line, char *out_buf);
-int lock_file(char *name);
-
-/*
- * If given a '-p' flag, read encoded delta pieces from stdin or file
- * arguments, decode them and assemble any completed deltas. If given
- * a '-b' flag, pass any completed deltas to 'ctm' for application to
- * the source tree. The '-d' flag is mandatory, but either of '-p' or
- * '-b' can be omitted. If given the '-l' flag, notes and errors will
- * be timestamped and written to the given file.
- *
- * Exit status is 0 for success or 1 for indigestible input. That is,
- * 0 means the encode input pieces were decoded and stored, and 1 means
- * some input was discarded. If a delta fails to apply, this won't be
- * reflected in the exit status. In this case, the delta is left in
- * 'deltadir'.
- */
-int
-main(int argc, char **argv)
- {
- char *log_file = NULL;
- int status = 0;
- int fork_ctm = 0;
-
- mask = umask(0);
- umask(mask);
-
- err_prog_name(argv[0]);
-
- OPTIONS("[-Dfuv] [-p piecedir] [-d deltadir] [-b basedir] [-l log] [file ...]")
- FLAG('D', delete_after)
- FLAG('f', fork_ctm)
- FLAG('u', set_time)
- FLAG('v', apply_verbose)
- STRING('p', piece_dir)
- STRING('d', delta_dir)
- STRING('b', base_dir)
- STRING('l', log_file)
- ENDOPTS
-
- if (delta_dir == NULL)
- usage();
-
- if (piece_dir == NULL && (base_dir == NULL || argc > 1))
- usage();
-
- if (log_file != NULL)
- err_set_log(log_file);
-
- /*
- * Digest each file in turn, or just stdin if no files were given.
- */
- if (argc <= 1)
- {
- if (piece_dir != NULL)
- status = read_piece(NULL);
- }
- else
- {
- while (*++argv != NULL)
- status |= read_piece(*argv);
- }
-
- /*
- * Maybe it's time to look for and apply completed deltas with ctm.
- *
- * Shall we report back to sendmail immediately, and let a child do
- * the work? Sendmail will be waiting for us to complete, delaying
- * other mail, and possibly some intermediate process (like MH slocal)
- * will terminate us if we take too long!
- *
- * If fork() fails, it's unlikely we'll be able to run ctm, so give up.
- * Also, the child exit status is unimportant.
- */
- if (base_dir != NULL)
- if (!fork_ctm || fork() == 0)
- apply_complete();
-
- return status;
- }
-
-
-/*
- * Construct the file name of a piece of a delta.
- */
-#define mk_piece_name(fn,d,p,n) \
- sprintf((fn), "%s/%s+%03d-%03d", piece_dir, (d), (p), (n))
-
-/*
- * Construct the file name of an assembled delta.
- */
-#define mk_delta_name(fn,d) \
- sprintf((fn), "%s/%s", delta_dir, (d))
-
-/*
- * If the next required delta is now present, let ctm lunch on it and any
- * contiguous deltas.
- */
-void
-apply_complete()
- {
- int i, dn;
- int lfd;
- FILE *fp, *ctm;
- struct stat sb;
- char class[20];
- char delta[30];
- char junk[2];
- char fname[PATH_MAX];
- char here[PATH_MAX];
- char buf[PATH_MAX*2];
-
- /*
- * Grab a lock on the ctm mutex file so that we can be sure we are
- * working alone, not fighting another ctm_rmail!
- */
- strcpy(fname, delta_dir);
- strcat(fname, "/.mutex_apply");
- if ((lfd = lock_file(fname)) < 0)
- return;
-
- /*
- * Find out which delta ctm needs next.
- */
- sprintf(fname, "%s/%s", base_dir, CTM_STATUS);
- if ((fp = fopen(fname, "r")) == NULL)
- {
- close(lfd);
- return;
- }
-
- i = fscanf(fp, "%19s %d %c", class, &dn, junk);
- fclose(fp);
- if (i != 2)
- {
- close(lfd);
- return;
- }
-
- /*
- * We might need to convert the delta filename to an absolute pathname.
- */
- here[0] = '\0';
- if (delta_dir[0] != '/')
- {
- getcwd(here, sizeof(here)-1);
- i = strlen(here) - 1;
- if (i >= 0 && here[i] != '/')
- {
- here[++i] = '/';
- here[++i] = '\0';
- }
- }
-
- /*
- * Keep applying deltas until we run out or something bad happens.
- */
- for (;;)
- {
- sprintf(delta, "%s.%04d.gz", class, ++dn);
- mk_delta_name(fname, delta);
-
- if (stat(fname, &sb) < 0)
- break;
-
- sprintf(buf, "(cd %s && ctm %s%s%s%s) 2>&1", base_dir,
- set_time ? "-u " : "",
- apply_verbose ? "-v " : "", here, fname);
- if ((ctm = popen(buf, "r")) == NULL)
- {
- err("ctm failed to apply %s", delta);
- break;
- }
-
- while (fgets(buf, sizeof(buf), ctm) != NULL)
- {
- i = strlen(buf) - 1;
- if (i >= 0 && buf[i] == '\n')
- buf[i] = '\0';
- err("ctm: %s", buf);
- }
-
- if (pclose(ctm) != 0)
- {
- err("ctm failed to apply %s", delta);
- break;
- }
-
- if (delete_after)
- unlink(fname);
-
- err("%s applied%s", delta, delete_after ? " and deleted" : "");
- }
-
- /*
- * Closing the lock file clears the lock.
- */
- close(lfd);
- }
-
-
-/*
- * This cheap plastic checksum effectively rotates our checksum-so-far
- * left one, then adds the character. We only want 16 bits of it, and
- * don't care what happens to the rest. It ain't much, but it's small.
- */
-#define add_ck(sum,x) \
- ((sum) += ((x)&0xff) + (sum) + (((sum)&0x8000) ? 1 : 0))
-
-
-/*
- * Decode the data between BEGIN and END, and stash it in the staging area.
- * Multiple pieces can be present in a single file, bracketed by BEGIN/END.
- * If we have all pieces of a delta, combine them. Returns 0 on success,
- * and 1 for any sort of failure.
- */
-int
-read_piece(char *input_file)
- {
- int status = 0;
- FILE *ifp, *ofp = 0;
- int decoding = 0;
- int got_one = 0;
- int line_no = 0;
- int i, n;
- int pce, npieces;
- unsigned claimed_cksum;
- unsigned short cksum = 0;
- char out_buf[200];
- char line[200];
- char delta[30];
- char pname[PATH_MAX];
- char tname[PATH_MAX];
- char junk[2];
-
- ifp = stdin;
- if (input_file != NULL && (ifp = fopen(input_file, "r")) == NULL)
- {
- err("cannot open '%s' for reading", input_file);
- return 1;
- }
-
- while (fgets(line, sizeof(line), ifp) != NULL)
- {
- line_no++;
-
- /*
- * Remove all trailing white space.
- */
- i = strlen(line) - 1;
- while (i > 0 && isspace(line[i]))
- line[i--] = '\0';
-
- /*
- * Look for the beginning of an encoded piece.
- */
- if (!decoding)
- {
- char *s;
- int fd = -1;
-
- if (sscanf(line, "CTM_MAIL BEGIN %29s %d %d %c",
- delta, &pce, &npieces, junk) != 3)
- continue;
-
- while ((s = strchr(delta, '/')) != NULL)
- *s = '_';
-
- got_one++;
- strcpy(tname, piece_dir);
- strcat(tname, "/p.XXXXXXXXXX");
- if ((fd = mkstemp(tname)) == -1 ||
- (ofp = fdopen(fd, "w")) == NULL)
- {
- if (fd != -1) {
- err("cannot open '%s' for writing", tname);
- close(fd);
- }
- else
- err("*mkstemp: '%s'", tname);
- status++;
- continue;
- }
-
- cksum = 0xffff;
- decoding++;
- continue;
- }
-
- /*
- * We are decoding. Stop if we see the end flag.
- */
- if (sscanf(line, "CTM_MAIL END %d %c", &claimed_cksum, junk) == 1)
- {
- int e;
-
- decoding = 0;
-
- fflush(ofp);
- e = ferror(ofp);
- fclose(ofp);
-
- if (e)
- err("error writing %s", tname);
-
- if (cksum != claimed_cksum)
- err("checksum: read %d, calculated %d", claimed_cksum, cksum);
-
- if (e || cksum != claimed_cksum)
- {
- err("%s %d/%d discarded", delta, pce, npieces);
- unlink(tname);
- status++;
- continue;
- }
-
- mk_piece_name(pname, delta, pce, npieces);
- if (rename(tname, pname) < 0)
- {
- err("*rename: '%s' to '%s'", tname, pname);
- err("%s %d/%d lost!", delta, pce, npieces);
- unlink(tname);
- status++;
- continue;
- }
-
- err("%s %d/%d stored", delta, pce, npieces);
-
- if (!combine_if_complete(delta, pce, npieces))
- status++;
- continue;
- }
-
- /*
- * Must be a line of encoded data. Decode it, sum it, and save it.
- */
- n = decode_line(line, out_buf);
- if (n <= 0)
- {
- err("line %d: illegal character: '%c'", line_no, line[-n]);
- err("%s %d/%d discarded", delta, pce, npieces);
-
- fclose(ofp);
- unlink(tname);
-
- status++;
- decoding = 0;
- continue;
- }
-
- for (i = 0; i < n; i++)
- add_ck(cksum, out_buf[i]);
-
- fwrite(out_buf, sizeof(char), n, ofp);
- }
-
- if (decoding)
- {
- err("truncated file");
- err("%s %d/%d discarded", delta, pce, npieces);
-
- fclose(ofp);
- unlink(tname);
-
- status++;
- }
-
- if (ferror(ifp))
- {
- err("error reading %s", input_file == NULL ? "stdin" : input_file);
- status++;
- }
-
- if (input_file != NULL)
- fclose(ifp);
-
- if (!got_one)
- {
- err("message contains no delta");
- status++;
- }
-
- return (status != 0);
- }
-
-
-/*
- * Put the pieces together to form a delta, if they are all present.
- * Returns 1 on success (even if we didn't do anything), and 0 on failure.
- */
-int
-combine_if_complete(char *delta, int pce, int npieces)
- {
- int i, e;
- int lfd;
- struct stat sb;
- char pname[PATH_MAX];
- char dname[PATH_MAX];
- char tname[PATH_MAX];
-
- /*
- * We can probably just rename() it into place if it is a small delta.
- */
- if (npieces == 1)
- {
- mk_delta_name(dname, delta);
- mk_piece_name(pname, delta, 1, 1);
- if (rename(pname, dname) == 0)
- {
- chmod(dname, 0666 & ~mask);
- err("%s complete", delta);
- return 1;
- }
- }
-
- /*
- * Grab a lock on the reassembly mutex file so that we can be sure we are
- * working alone, not fighting another ctm_rmail!
- */
- strcpy(tname, delta_dir);
- strcat(tname, "/.mutex_build");
- if ((lfd = lock_file(tname)) < 0)
- return 0;
-
- /*
- * Are all of the pieces present? Of course the current one is,
- * unless all pieces are missing because another ctm_rmail has
- * processed them already.
- */
- for (i = 1; i <= npieces; i++)
- {
- if (i == pce)
- continue;
- mk_piece_name(pname, delta, i, npieces);
- if (stat(pname, &sb) < 0)
- {
- close(lfd);
- return 1;
- }
- }
-
- /*
- * Stick them together. Let combine() use our file name buffers, since
- * we're such good buddies. :-)
- */
- e = combine(delta, npieces, dname, pname, tname);
- close(lfd);
- return e;
- }
-
-
-/*
- * Put the pieces together to form a delta.
- * Returns 1 on success, and 0 on failure.
- * Note: dname, pname, and tname are room for some file names that just
- * happened to by lying around in the calling routine. Waste not, want not!
- */
-int
-combine(char *delta, int npieces, char *dname, char *pname, char *tname)
- {
- FILE *dfp, *pfp;
- int i, n, e;
- char buf[BUFSIZ];
- int fd = -1;
-
- strcpy(tname, delta_dir);
- strcat(tname, "/d.XXXXXXXXXX");
- if ((fd = mkstemp(tname)) == -1 ||
- (dfp = fdopen(fd, "w")) == NULL)
- {
- if (fd != -1) {
- close(fd);
- err("cannot open '%s' for writing", tname);
- }
- else
- err("*mkstemp: '%s'", tname);
- return 0;
- }
-
- /*
- * Reconstruct the delta by reading each piece in order.
- */
- for (i = 1; i <= npieces; i++)
- {
- mk_piece_name(pname, delta, i, npieces);
- if ((pfp = fopen(pname, "r")) == NULL)
- {
- err("cannot open '%s' for reading", pname);
- fclose(dfp);
- unlink(tname);
- return 0;
- }
- while ((n = fread(buf, sizeof(char), sizeof(buf), pfp)) != 0)
- fwrite(buf, sizeof(char), n, dfp);
- e = ferror(pfp);
- fclose(pfp);
- if (e)
- {
- err("error reading '%s'", pname);
- fclose(dfp);
- unlink(tname);
- return 0;
- }
- }
- fflush(dfp);
- e = ferror(dfp);
- fclose(dfp);
- if (e)
- {
- err("error writing '%s'", tname);
- unlink(tname);
- return 0;
- }
-
- mk_delta_name(dname, delta);
- if (rename(tname, dname) < 0)
- {
- err("*rename: '%s' to '%s'", tname, dname);
- unlink(tname);
- return 0;
- }
- chmod(dname, 0666 & ~mask);
-
- /*
- * Throw the pieces away.
- */
- for (i = 1; i <= npieces; i++)
- {
- mk_piece_name(pname, delta, i, npieces);
- if (unlink(pname) < 0)
- err("*unlink: '%s'", pname);
- }
-
- err("%s complete", delta);
- return 1;
- }
-
-
-/*
- * MIME BASE64 decode table.
- */
-static unsigned char from_b64[0x80] =
- {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
- 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
- 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
- 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
- 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
- 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
- };
-
-
-/*
- * Decode a line of ASCII into binary. Returns the number of bytes in
- * the output buffer, or < 0 on indigestable input. Error output is
- * the negative of the index of the inedible character.
- */
-int
-decode_line(char *line, char *out_buf)
- {
- unsigned char *ip = (unsigned char *)line;
- unsigned char *op = (unsigned char *)out_buf;
- unsigned long bits;
- unsigned x;
-
- for (;;)
- {
- if (*ip >= 0x80 || (x = from_b64[*ip]) >= 0x40)
- break;
- bits = x << 18;
- ip++;
- if (*ip < 0x80 && (x = from_b64[*ip]) < 0x40)
- {
- bits |= x << 12;
- *op++ = bits >> 16;
- ip++;
- if (*ip < 0x80 && (x = from_b64[*ip]) < 0x40)
- {
- bits |= x << 6;
- *op++ = bits >> 8;
- ip++;
- if (*ip < 0x80 && (x = from_b64[*ip]) < 0x40)
- {
- bits |= x;
- *op++ = bits;
- ip++;
- }
- }
- }
- }
-
- if (*ip == '\0' || *ip == '\n')
- return op - (unsigned char *)out_buf;
- else
- return -(ip - (unsigned char *)line);
- }
-
-
-/*
- * Create and lock the given file.
- *
- * Clearing the lock is as simple as closing the file descriptor we return.
- */
-int
-lock_file(char *name)
- {
- int lfd;
-
- if ((lfd = open(name, O_WRONLY|O_CREAT, 0600)) < 0)
- {
- err("*open: '%s'", name);
- return -1;
- }
- if (flock(lfd, LOCK_EX) < 0)
- {
- close(lfd);
- err("*flock: '%s'", name);
- return -1;
- }
- return lfd;
- }
diff --git a/usr.sbin/ctm/ctm_rmail/error.c b/usr.sbin/ctm/ctm_rmail/error.c
deleted file mode 100644
index 56d3dc68d5f7..000000000000
--- a/usr.sbin/ctm/ctm_rmail/error.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Routines for logging error messages or other informative messages.
- *
- * Log messages can easily contain the program name, a time stamp, system
- * error messages, and arbitrary printf-style strings, and can be directed
- * to stderr or a log file.
- *
- * Author: Stephen McKay
- *
- * NOTICE: This is free software. I hope you get some use from this program.
- * In return you should think about all the nice people who give away software.
- * Maybe you should write some free software too.
- */
-
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
-#include <errno.h>
-#include "error.h"
-
-static FILE *error_fp = NULL;
-static char *prog = NULL;
-
-
-/*
- * Log errors to the given file.
- */
-void
-err_set_log(char *log_file)
- {
- FILE *fp;
-
- if ((fp = fopen(log_file, "a")) == NULL)
- err("cannot log to '%s'", log_file);
- else
- error_fp = fp;
- }
-
-
-/*
- * Set the error prefix if not logging to a file.
- */
-void
-err_prog_name(char *name)
- {
- if ((prog = strrchr(name, '/')) == NULL)
- prog = name;
- else
- prog++;
- }
-
-
-/*
- * Log an error.
- *
- * A leading '*' in the message format means we want the system errno
- * decoded and appended.
- */
-void
-err(const char *fmt, ...)
- {
- va_list ap;
- time_t now;
- struct tm *tm;
- FILE *fp;
- int x = errno;
- int want_errno;
-
- if ((fp = error_fp) == NULL)
- {
- fp = stderr;
- if (prog != NULL)
- fprintf(fp, "%s: ", prog);
- }
- else
- {
- time(&now);
- tm = localtime(&now);
- fprintf(fp, "%04d-%02d-%02d %02d:%02d ", tm->tm_year+1900,
- tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
- }
-
- want_errno = 0;
- if (*fmt == '*')
- want_errno++, fmt++;
-
- va_start(ap, fmt);
- vfprintf(fp, fmt, ap);
- va_end(ap);
-
- if (want_errno)
- fprintf(fp, ": %s", strerror(x));
-
- fprintf(fp, "\n");
- fflush(fp);
- }
diff --git a/usr.sbin/ctm/ctm_rmail/error.h b/usr.sbin/ctm/ctm_rmail/error.h
deleted file mode 100644
index c631b6712ccb..000000000000
--- a/usr.sbin/ctm/ctm_rmail/error.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/* $FreeBSD$ */
-
-extern void err_set_log(char *log_file);
-extern void err_prog_name(char *name);
-extern void err(const char *fmt, ...) __printflike(1, 2);
diff --git a/usr.sbin/ctm/ctm_rmail/options.h b/usr.sbin/ctm/ctm_rmail/options.h
deleted file mode 100644
index 86c1247b6487..000000000000
--- a/usr.sbin/ctm/ctm_rmail/options.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Macros for processing command arguments.
- *
- * Conforms closely to the command option requirements of intro(1) in System V
- * and intro(C) in Xenix.
- *
- * A command consists of: cmdname [ options ] [ cmdarguments ]
- *
- * Options consist of a leading dash '-' and a flag letter. An argument may
- * follow optionally preceded by white space.
- * Options without arguments may be grouped behind a single dash.
- * A dash on its own is interpreted as the end of the options and is retained
- * as a command argument.
- * A double dash '--' is interpreted as the end of the options and is discarded.
- *
- * For example:
- * zap -xz -f flame -q34 -- -x
- *
- * where zap.c contains the following in main():
- *
- * OPTIONS("[-xz] [-q queue-id] [-f dump-file] user")
- * FLAG('x', xecute)
- * FLAG('z', zot)
- * STRING('f', file)
- * fp = fopen(file, "w");
- * NUMBER('q', queue)
- * ENDOPTS
- *
- * Results in:
- * xecute = 1
- * zot = 1
- * file = "flame"
- * fp = fopen("flame", "w")
- * queue = 34
- * argc = 2
- * argv[0] = "zap"
- * argv[1] = "-x"
- *
- * Should the user enter unknown flags or leave out required arguments,
- * the message:
- *
- * Usage: zap [-xz] [-q queue-id] [-f dump-file] user
- *
- * will be printed. This message can be printed by calling pusage(), or
- * usage(). usage() will also cause program termination with exit code 1.
- *
- * Author: Stephen McKay, February 1991
- *
- * Based on recollection of the original options.h produced at the University
- * of Queensland by Ross Patterson (and possibly others).
- *
- * $FreeBSD$
- */
-
-static char *O_usage;
-static char *O_name;
-extern long atol();
-
-void
-pusage()
- {
- /*
- * Avoid gratuitously loading stdio.
- */
- write(STDERR_FILENO, "usage: ", 7);
- write(STDERR_FILENO, O_name, strlen(O_name));
- write(STDERR_FILENO, " ", 1);
- write(STDERR_FILENO, O_usage, strlen(O_usage));
- write(STDERR_FILENO, "\n", 1);
- }
-
-#define usage() (pusage(), exit(1))
-
-#define OPTIONS(usage_msg) \
- { \
- char O_cont; \
- O_usage = (usage_msg); \
- O_name = argv[0]; \
- while (*++argv && **argv == '-') \
- { \
- if ((*argv)[1] == '\0') \
- break; \
- argc--; \
- if ((*argv)[1] == '-' && (*argv)[2] == '\0') \
- { \
- argv++; \
- break; \
- } \
- O_cont = 1; \
- while (O_cont) \
- switch (*++*argv) \
- { \
- default: \
- case '-': \
- usage(); \
- case '\0': \
- O_cont = 0;
-
-#define FLAG(x,flag) \
- break; \
- case (x): \
- (flag) = 1;
-
-#define CHAR(x,ch) \
- break; \
- case (x): \
- O_cont = 0; \
- if (*++*argv == '\0' && (--argc, *++argv == 0)) \
- usage(); \
- (ch) = **argv;
-
-#define NUMBER(x,n) \
- break; \
- case (x): \
- O_cont = 0; \
- if (*++*argv == '\0' && (--argc, *++argv == 0)) \
- usage(); \
- (n) = atol(*argv);
-
-#define STRING(x,str) \
- break; \
- case (x): \
- O_cont = 0; \
- if (*++*argv == '\0' && (--argc, *++argv == 0)) \
- usage(); \
- (str) = *argv;
-
-#define SUFFIX(x,str) \
- break; \
- case (x): \
- (str) = ++*argv; \
- O_cont = 0;
-
-#define ENDOPTS \
- break; \
- } \
- } \
- *--argv = O_name; \
- }
diff --git a/usr.sbin/ctm/ctm_smail/Makefile b/usr.sbin/ctm/ctm_smail/Makefile
deleted file mode 100644
index 88e8c21f60b4..000000000000
--- a/usr.sbin/ctm/ctm_smail/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${.CURDIR:H}/ctm_rmail
-
-PROG= ctm_smail
-MAN=
-SRCS= ctm_smail.c error.c
-
-CFLAGS+= -I${.CURDIR:H}/ctm_rmail
-
-WARNS?= 2
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/ctm/ctm_smail/Makefile.depend b/usr.sbin/ctm/ctm_smail/Makefile.depend
deleted file mode 100644
index 6cfaab1c3644..000000000000
--- a/usr.sbin/ctm/ctm_smail/Makefile.depend
+++ /dev/null
@@ -1,17 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/ctm/ctm_smail/ctm_smail.c b/usr.sbin/ctm/ctm_smail/ctm_smail.c
deleted file mode 100644
index 72c5ae741f3f..000000000000
--- a/usr.sbin/ctm/ctm_smail/ctm_smail.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Send a compressed CTM delta to a recipient mailing list by encoding it
- * in safe ASCII characters, in mailer-friendly chunks, and passing them
- * to sendmail. Optionally, the chunks can be queued to be sent later by
- * ctm_dequeue in controlled bursts. The encoding is almost the same as
- * MIME BASE64, and is protected by a simple checksum.
- *
- * Author: Stephen McKay
- *
- * NOTICE: This is free software. I hope you get some use from this program.
- * In return you should think about all the nice people who give away software.
- * Maybe you should write some free software too.
- *
- * $FreeBSD$
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <paths.h>
-#include <limits.h>
-#include "error.h"
-#include "options.h"
-
-#define DEF_MAX_MSG 64000 /* Default maximum mail msg minus headers. */
-
-#define LINE_LENGTH 72 /* Chars per encoded line. Divisible by 4. */
-
-int chop_and_send_or_queue(FILE *dfp, char *delta, off_t ctm_size,
- long max_msg_size, char *mail_alias, char *queue_dir);
-int chop_and_send(FILE *dfp, char *delta, long msg_size, int npieces,
- char *mail_alias);
-int chop_and_queue(FILE *dfp, char *delta, long msg_size, int npieces,
- char *mail_alias, char *queue_dir);
-void clean_up_queue(char *queue_dir);
-int encode_body(FILE *sm_fp, FILE *delta_fp, long msg_size, unsigned *sum);
-void write_header(FILE *sfp, char *mail_alias, char *delta, int pce,
- int npieces);
-void write_trailer(FILE *sfp, unsigned sum);
-int apologise(char *delta, off_t ctm_size, long max_ctm_size,
- char *mail_alias, char *queue_dir);
-FILE *open_sendmail(void);
-int close_sendmail(FILE *fp);
-
-int
-main(int argc, char **argv)
- {
- int status = 0;
- char *delta_file;
- char *mail_alias;
- long max_msg_size = DEF_MAX_MSG;
- long max_ctm_size = 0;
- char *log_file = NULL;
- char *queue_dir = NULL;
- char *delta;
- FILE *dfp;
- struct stat sb;
-
- err_prog_name(argv[0]);
-
- OPTIONS("[-l log] [-m maxmsgsize] [-c maxctmsize] [-q queuedir] ctm-delta mail-alias")
- NUMBER('m', max_msg_size)
- NUMBER('c', max_ctm_size)
- STRING('l', log_file)
- STRING('q', queue_dir)
- ENDOPTS
-
- if (argc != 3)
- usage();
-
- if (log_file != NULL)
- err_set_log(log_file);
-
- delta_file = argv[1];
- mail_alias = argv[2];
-
- if ((delta = strrchr(delta_file, '/')) == NULL)
- delta = delta_file;
- else
- delta++;
-
- if ((dfp = fopen(delta_file, "r")) == NULL || fstat(fileno(dfp), &sb) < 0)
- {
- err("*%s", delta_file);
- exit(1);
- }
-
- if (max_ctm_size != 0 && sb.st_size > max_ctm_size)
- status = apologise(delta, sb.st_size, max_ctm_size, mail_alias,
- queue_dir);
- else
- status = chop_and_send_or_queue(dfp, delta, sb.st_size, max_msg_size,
- mail_alias, queue_dir);
-
- fclose(dfp);
-
- return status;
- }
-
-
-/*
- * Carve our CTM delta into pieces, encode them, and send or queue them.
- * Returns 0 on success, and 1 on failure.
- */
-int
-chop_and_send_or_queue(FILE *dfp, char *delta, off_t ctm_size,
- long max_msg_size, char *mail_alias, char *queue_dir)
- {
- int npieces;
- long msg_size;
- long exp_size;
- int status;
-
-#undef howmany
-#define howmany(x,y) (((x)+((y)-1)) / (y))
-
- /*
- * Work out how many pieces we need, bearing in mind that each piece
- * grows by 4/3 when encoded. We count the newlines too, but ignore
- * all mail headers and piece headers. They are a "small" (almost
- * constant) per message overhead that we make the user worry about. :-)
- */
- exp_size = ctm_size * 4 / 3;
- exp_size += howmany(exp_size, LINE_LENGTH);
- npieces = howmany(exp_size, max_msg_size);
- msg_size = howmany(ctm_size, npieces);
-
-#undef howmany
-
- if (queue_dir == NULL)
- status = chop_and_send(dfp, delta, msg_size, npieces, mail_alias);
- else
- {
- status = chop_and_queue(dfp, delta, msg_size, npieces, mail_alias,
- queue_dir);
- if (status)
- clean_up_queue(queue_dir);
- }
-
- return status;
- }
-
-
-/*
- * Carve our CTM delta into pieces, encode them, and send them.
- * Returns 0 on success, and 1 on failure.
- */
-int
-chop_and_send(FILE *dfp, char *delta, long msg_size, int npieces,
- char *mail_alias)
- {
- int pce;
- FILE *sfp;
- unsigned sum;
-
- /*
- * Send each chunk directly to sendmail as it is generated.
- * No temporary files necessary. If things turn ugly, we just
- * have to live with the fact the we have sent only part of
- * the delta.
- */
- for (pce = 1; pce <= npieces; pce++)
- {
- int read_error;
-
- if ((sfp = open_sendmail()) == NULL)
- return 1;
-
- write_header(sfp, mail_alias, delta, pce, npieces);
- read_error = encode_body(sfp, dfp, msg_size, &sum);
- if (!read_error)
- write_trailer(sfp, sum);
-
- if (!close_sendmail(sfp) || read_error)
- return 1;
-
- err("%s %d/%d sent to %s", delta, pce, npieces, mail_alias);
- }
-
- return 0;
- }
-
-
-/*
- * Construct the tmp queue file name of a delta piece.
- */
-#define mk_tmp_name(fn,qd,p) \
- snprintf((fn), sizeof(fn), "%s/.%08ld.%03d", (qd), (long)getpid(), (p))
-
-/*
- * Construct the final queue file name of a delta piece.
- */
-#define mk_queue_name(fn,qd,d,p,n) \
- snprintf((fn), sizeof(fn), "%s/%s+%03d-%03d", (qd), (d), (p), (n))
-
-/*
- * Carve our CTM delta into pieces, encode them, and queue them.
- * Returns 0 on success, and 1 on failure.
- */
-int
-chop_and_queue(FILE *dfp, char *delta, long msg_size, int npieces,
- char *mail_alias, char *queue_dir)
- {
- int pce;
- FILE *qfp;
- unsigned sum;
- char tname[PATH_MAX];
- char qname[PATH_MAX];
-
- /*
- * Store each piece in the queue directory, but under temporary names,
- * so that they can be deleted without unpleasant consequences if
- * anything goes wrong. We could easily fill up a disk, for example.
- */
- for (pce = 1; pce <= npieces; pce++)
- {
- int write_error;
-
- mk_tmp_name(tname, queue_dir, pce);
- if ((qfp = fopen(tname, "w")) == NULL)
- {
- err("cannot open '%s' for writing", tname);
- return 1;
- }
-
- write_header(qfp, mail_alias, delta, pce, npieces);
- if (encode_body(qfp, dfp, msg_size, &sum))
- return 1;
- write_trailer(qfp, sum);
-
- fflush(qfp);
- write_error = ferror(qfp);
- fclose(qfp);
- if (write_error)
- {
- err("error writing '%s'", tname);
- return 1;
- }
-
- /*
- * Give the warm success message now, instead of all in a rush
- * during the rename phase.
- */
- err("%s %d/%d queued for %s", delta, pce, npieces, mail_alias);
- }
-
- /*
- * Rename the pieces into place. If an error occurs now, we are
- * stuffed, but there is no neat way to back out. rename() should
- * only fail now under extreme circumstances.
- */
- for (pce = 1; pce <= npieces; pce++)
- {
- mk_tmp_name(tname, queue_dir, pce);
- mk_queue_name(qname, queue_dir, delta, pce, npieces);
- if (rename(tname, qname) < 0)
- {
- err("*rename: '%s' to '%s'", tname, qname);
- unlink(tname);
- }
- }
-
- return 0;
- }
-
-
-/*
- * There may be temporary files cluttering up the queue directory.
- */
-void
-clean_up_queue(char *queue_dir)
- {
- int pce;
- char tname[PATH_MAX];
-
- err("discarding queued delta pieces");
- for (pce = 1; ; pce++)
- {
- mk_tmp_name(tname, queue_dir, pce);
- if (unlink(tname) < 0)
- break;
- }
- }
-
-
-/*
- * MIME BASE64 encode table.
- */
-static char to_b64[0x40] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-/*
- * This cheap plastic checksum effectively rotates our checksum-so-far
- * left one, then adds the character. We only want 16 bits of it, and
- * don't care what happens to the rest. It ain't much, but it's small.
- */
-#define add_ck(sum,x) \
- ((sum) += ((x)&0xff) + (sum) + (((sum)&0x8000) ? 1 : 0))
-
-/*
- * Encode the body. Use an encoding almost the same as MIME BASE64.
- *
- * Characters are read from delta_fp and encoded characters are written
- * to sm_fp. At most 'msg_size' characters should be read from delta_fp.
- *
- * The body consists of lines of up to LINE_LENGTH characters. Each group
- * of 4 characters encodes 3 input characters. Each output character encodes
- * 6 bits. Thus 64 different characters are needed in this representation.
- */
-int
-encode_body(FILE *sm_fp, FILE *delta_fp, long msg_size, unsigned *sum)
- {
- unsigned short cksum = 0xffff;
- unsigned char *ip;
- char *op;
- int want, n, i;
- unsigned char inbuf[LINE_LENGTH*3/4];
- char outbuf[LINE_LENGTH+1];
-
- /*
- * Round up to the nearest line boundary, for the tiniest of gains,
- * and lots of neatness. :-)
- */
- msg_size += (LINE_LENGTH*3/4) - 1;
- msg_size -= msg_size % (LINE_LENGTH*3/4);
-
- while (msg_size > 0)
- {
- want = (msg_size < sizeof(inbuf)) ? msg_size : sizeof(inbuf);
- if ((n = fread(inbuf, sizeof(char), want, delta_fp)) == 0)
- break;
- msg_size -= n;
-
- for (i = 0; i < n; i++)
- add_ck(cksum, inbuf[i]);
-
- /*
- * Produce a line of encoded data. Every line length will be a
- * multiple of 4, except for, perhaps, the last line.
- */
- ip = inbuf;
- op = outbuf;
- while (n >= 3)
- {
- *op++ = to_b64[ip[0] >> 2];
- *op++ = to_b64[(ip[0] << 4 & 0x3f) | ip[1] >> 4];
- *op++ = to_b64[(ip[1] << 2 & 0x3f) | ip[2] >> 6];
- *op++ = to_b64[ip[2] & 0x3f];
- ip += 3;
- n -= 3;
- }
- if (n > 0)
- {
- *op++ = to_b64[ip[0] >> 2];
- *op++ = to_b64[(ip[0] << 4 & 0x3f) | ip[1] >> 4];
- if (n >= 2)
- *op++ = to_b64[ip[1] << 2 & 0x3f];
- }
- *op++ = '\n';
- fwrite(outbuf, sizeof(char), op - outbuf, sm_fp);
- }
-
- if (ferror(delta_fp))
- {
- err("error reading input file.");
- return 1;
- }
-
- *sum = cksum;
-
- return 0;
- }
-
-
-/*
- * Write the mail header and data header.
- */
-void
-write_header(FILE *sfp, char *mail_alias, char *delta, int pce, int npieces)
- {
- fprintf(sfp, "From: owner-%s\n", mail_alias);
- fprintf(sfp, "To: %s\n", mail_alias);
- fprintf(sfp, "Subject: ctm-mail %s %d/%d\n\n", delta, pce, npieces);
-
- fprintf(sfp, "CTM_MAIL BEGIN %s %d %d\n", delta, pce, npieces);
- }
-
-
-/*
- * Write the data trailer.
- */
-void
-write_trailer(FILE *sfp, unsigned sum)
- {
- fprintf(sfp, "CTM_MAIL END %ld\n", (long)sum);
- }
-
-
-/*
- * We're terribly sorry, but the delta is too big to send.
- * Returns 0 on success, 1 on failure.
- */
-int
-apologise(char *delta, off_t ctm_size, long max_ctm_size, char *mail_alias,
- char *queue_dir)
- {
- FILE *sfp;
- char qname[PATH_MAX];
-
- if (queue_dir == NULL)
- {
- sfp = open_sendmail();
- if (sfp == NULL)
- return 1;
- }
- else
- {
- mk_queue_name(qname, queue_dir, delta, 1, 1);
- sfp = fopen(qname, "w");
- if (sfp == NULL)
- {
- err("cannot open '%s' for writing", qname);
- return 1;
- }
- }
-
-
- fprintf(sfp, "From: owner-%s\n", mail_alias);
- fprintf(sfp, "To: %s\n", mail_alias);
- fprintf(sfp, "Subject: ctm-notice %s\n\n", delta);
-
- fprintf(sfp, "%s is %ld bytes. The limit is %ld bytes.\n\n", delta,
- (long)ctm_size, max_ctm_size);
- fprintf(sfp, "You can retrieve this delta via ftp.\n");
-
- if (queue_dir == NULL)
- {
- if (!close_sendmail(sfp))
- return 1;
- }
- else
- {
- if (fclose(sfp)!=0)
- {
- err("error writing '%s'", qname);
- unlink(qname);
- return 1;
- }
- }
-
- return 0;
- }
-
-
-/*
- * Start a pipe to sendmail. Sendmail will decode the destination
- * from the message contents.
- */
-FILE *
-open_sendmail()
- {
- FILE *fp;
- char buf[100];
-
- sprintf(buf, "%s -odq -t", _PATH_SENDMAIL);
- if ((fp = popen(buf, "w")) == NULL)
- err("cannot start sendmail");
- return fp;
- }
-
-
-/*
- * Close a pipe to sendmail. Sendmail will then do its bit.
- * Return 1 on success, 0 on failure.
- */
-int
-close_sendmail(FILE *fp)
- {
- int status;
-
- fflush(fp);
- if (ferror(fp))
- {
- err("error writing to sendmail");
- return 0;
- }
-
- if ((status = pclose(fp)) != 0)
- err("sendmail failed with status %d", status);
-
- return (status == 0);
- }
diff --git a/usr.sbin/ctm/mkCTM/Makefile b/usr.sbin/ctm/mkCTM/Makefile
deleted file mode 100644
index 8194dd7f8278..000000000000
--- a/usr.sbin/ctm/mkCTM/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-# $FreeBSD$
-
-PROG= mkctm
-MAN=
-
-LIBADD= md
-
-test: mkctm
- rm -f tst.out*
- time ./mkctm -v -v /3c/210src /a/r1/usr/src \
- 2>a | md5 -p > /a/tst.out
- ls -l /a/tst.out
- gzip -9 -v /a/tst.out
- ls -l /a/tst.out.gz
- # cd /usr/src/release && ctm -c -v -v ${.CURDIR}/tst.out
-
-test1: mkctm
- rm -f tst.out*
- time ./mkctm -v -v /3c/210src /home/ncvs/src \
- 2> b | md5 -p > /a/tst2.out
- ls -l /a/tst2.out
- gzip -9 -v /a/tst2.out
- ls -l /a/tst2.out.gz
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/ctm/mkCTM/ctm_conf.cvs-cur b/usr.sbin/ctm/mkCTM/ctm_conf.cvs-cur
deleted file mode 100644
index fbb5bf26ce73..000000000000
--- a/usr.sbin/ctm/mkCTM/ctm_conf.cvs-cur
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/local/bin/tclsh
-
-set CTMname cvs-cur
-set CTMref /home/ncvs
-set CTMignore {^src/secure|^src/eBones|^src/kerberosIV|^CVSROOT/val-tags$|CVSROOT/\\.#}
-set CTMbogus {\\.core$|/#cvs|/\\.#}
-set CTMmail [email protected]
-set CTMqueuemail [email protected]
-set CTMqueue /home/ctm/queue/ctm-cvs-cur
diff --git a/usr.sbin/ctm/mkCTM/ctm_conf.ports-cur b/usr.sbin/ctm/mkCTM/ctm_conf.ports-cur
deleted file mode 100644
index b9d3d13a102e..000000000000
--- a/usr.sbin/ctm/mkCTM/ctm_conf.ports-cur
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/local/bin/tclsh
-
-set CTMname ports-cur
-set CTMref /usr/ports
-set CTMignore {/CVS$|/CVS/|^distfiles}
-set CTMbogus {\\.core$|/#cvs|/\\.#}
-set CTMmail [email protected]
diff --git a/usr.sbin/ctm/mkCTM/ctm_conf.smp-cur b/usr.sbin/ctm/mkCTM/ctm_conf.smp-cur
deleted file mode 100644
index 5c3e1d1bf211..000000000000
--- a/usr.sbin/ctm/mkCTM/ctm_conf.smp-cur
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/local/bin/tclsh
-
-set CTMname smp-cur
-set CTMref /home/smp
-set CTMignore {^CVSROOT/history.*$|^CVSROOT/val-tags$|^CVSROOT/\\.#}
-set CTMbogus {\\.core$|/#cvs|/\\.#}
-set CTMmail [email protected]
diff --git a/usr.sbin/ctm/mkCTM/ctm_conf.src-cur b/usr.sbin/ctm/mkCTM/ctm_conf.src-cur
deleted file mode 100644
index 8589d040efb8..000000000000
--- a/usr.sbin/ctm/mkCTM/ctm_conf.src-cur
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/local/bin/tclsh
-
-set CTMname src-cur
-set CTMref /c/src
-set CTMignore {/CVS$|/CVS/|^/secure|^/eBones}
-set CTMbogus {\\.core$|/#cvs|/\\.#}
-set CTMmail [email protected]
-set CTMqueue /home/ctm/queue/ctm-src-cur
-set CTMqueuemail [email protected]
diff --git a/usr.sbin/ctm/mkCTM/ctm_conf.src-special b/usr.sbin/ctm/mkCTM/ctm_conf.src-special
deleted file mode 100644
index 2a8ca70aeb66..000000000000
--- a/usr.sbin/ctm/mkCTM/ctm_conf.src-special
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/local/bin/tclsh
-
-set CTMname src-cur
-set CTMref $CTMSW/../$CTMname
-set CTMcopy /c/phk/20R/usr/src
-set CTMdont {\.core$|/CVS$|/CVS/|^/secure|^/eBones|/#cvs|/\.#}
-set CTMtest 1
-set CTMspecial 1
-set CTMsuff R20
diff --git a/usr.sbin/ctm/mkCTM/dequeue b/usr.sbin/ctm/mkCTM/dequeue
deleted file mode 100755
index 697ec0b5be85..000000000000
--- a/usr.sbin/ctm/mkCTM/dequeue
+++ /dev/null
@@ -1,6 +0,0 @@
-#! /bin/sh
-# $FreeBSD$
-
-L=/home/ctm/log.dequeue
-/usr/sbin/ctm_dequeue -n 1 -l $L /home/ctm/queue/ctm-cvs-cur
-/usr/sbin/ctm_dequeue -n 1 -l $L /home/ctm/queue/ctm-src-cur
diff --git a/usr.sbin/ctm/mkCTM/mkCTM b/usr.sbin/ctm/mkCTM/mkCTM
deleted file mode 100644
index 02b154427e9a..000000000000
--- a/usr.sbin/ctm/mkCTM/mkCTM
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/local/bin/tclsh7.4
-#
-# $FreeBSD$
-
-#############################################################################
-### Do we already have this delta ?
-#############################################################################
-
-proc find_delta {nbr} {
- global CTMname CTMdest
- if {[file exists [format "%s/$CTMname.%04d" $CTMdest $nbr]]} { return 1 }
- if {[file exists [format "%s/$CTMname.%04d.gz" $CTMdest $nbr]]} { return 1 }
- return 0
-}
-
-#############################################################################
-### The top level code...
-#############################################################################
-
-set CTMSW /home/ctm/SW
-
-cd $CTMSW
-
-# Defaults...
-set CTMapply 1
-set CTMignore {^///}
-set CTMbogus {\.core$}
-set CTMmail {}
-set CTMqueue {}
-set CTMqueuemail {}
-set CTMmaxctm 10000000
-set CTMmaxmsg 100000
-set CTMsuff {}
-set CTMdate [exec date -u +%Y%m%d%H%M%SZ]
-set CTMtmp {}
-set CTMcopy {}
-set CTMdest {}
-set CTMprefix .
-set CTMtest 0
-set CTMspecial 0
-set CTMscan .
-set CTMfirst 0
-set max_damage 100
-
-set damage 0
-set changes 0
-
-source $argv
-exec sh -c "date -u '+%Y%m%d%H%M%S $argv'" >> ${CTMSW}/log
-
-if {$CTMtmp == ""} {
- set CTMtmp $CTMSW/../tmp/${CTMname}_${CTMsuff}
-}
-if {$CTMcopy == ""} {
- set CTMcopy $CTMSW/../$CTMname
-}
-if {$CTMdest == ""} {
- set CTMdest $CTMSW/../CTM-pub/$CTMname
-}
-
-# Make sure we only run one at a time...
-
-set CTMlock Lck.${CTMname}.${CTMdate}.[pid]
-exec rm -f ${CTMlock}
-exec echo starting > ${CTMlock}
-if {[catch "exec ln $CTMlock LCK.$CTMname" a]} {
- puts "Not going, lock exists..."
- exec rm -f $CTMlock
- exit 1
-}
-exec rm -f $CTMlock
-set CTMlock LCK.$CTMname
-
-set CTMscratch ${CTMtmp}.tmp
-
-while 1 {
- if { ! $CTMspecial} {
- if {$CTMfirst} {
- set CTMnbr 0
- } else {
- set CTMnbr [lindex [exec cat $CTMcopy/.ctm_status] 1]
- }
-
- if {$CTMnbr > 0 && ![find_delta $CTMnbr]} {
- puts "$CTMname delta $CTMnbr doesn't exist..."
- exec rm -f $CTMlock
- exit 1
- }
-
- incr CTMnbr
-
- if {[find_delta $CTMnbr]} {
- puts "$CTMname delta $CTMnbr does already exist..."
- exec rm -f $CTMlock
- exit 1
- }
-
- set fo [open $CTMref/.ctm_status w]
- puts $fo "$CTMname $CTMnbr"
- close $fo
- incr changes -1
-
- } else {
- set CTMnbr [lindex [exec cat $CTMref/.ctm_status] 1]
- }
-
- puts "Doing CTMname $CTMname CTMnbr $CTMnbr$CTMsuff CTMdate $CTMdate"
- flush stdout
- exec sh -c "rm -f ${CTMtmp}.* ${CTMtmp}:*" >&@ stdout
-
- set nm [format "%s.%04d%s" $CTMname $CTMnbr $CTMsuff]
-
- set x1 $CTMcopy
- if {$x1 == ""} {
- exec mkdir ${CTMtmp}.dir
- set x1 ${CTMtmp}.dir
- }
- set r1 [catch "exec ${CTMSW}/mkctm -I ${CTMignore} -B ${CTMbogus} -l ${CTMtmp}.log -D $max_damage $CTMname $CTMnbr $CTMdate . $x1 $CTMref | md5 -p | gzip -9 > ${CTMtmp}:${nm}.gz 2>@ stderr" r2]
-
- if {$r1} {
- if {[lindex $errorCode 2] == 4} {
- puts "No changes, stopping."
- exec rm -f $CTMlock
- exit 0
- }
- puts "problems, stopping now."
- puts "errorCode $errorCode"
- puts "$r2"
- exec rm -f $CTMlock
- exit 1
- }
-
- puts "mkctm done"
-
- if {$CTMtest} {
- puts "testing, stopping now."
- exec rm -f $CTMlock
- exit 0
- }
- if {$CTMapply} {
- puts "Applying delta"
- flush stdout
- exec echo now applying > $CTMlock
- exec sh -e -c "cd $CTMcopy ; $CTMSW/ctm -v -v -v ${CTMtmp}:${nm}.gz" >& ${CTMtmp}.apply
- exec echo did apply > $CTMlock
- }
- puts "Moving delta"
- flush stdout
- exec mv ${CTMtmp}:${nm}.gz $CTMdest/.CTMtmp_${nm}.gz >&@ stdout
- exec mv $CTMdest/.CTMtmp_${nm}.gz $CTMdest/${nm}.gz >&@ stdout
- exec echo moved > $CTMlock
-
- exec sh -c "rm -rf ${CTMtmp}.*" >&@ stdout
-
- if {$CTMmail != ""} {
- puts "Mailing delta"
- flush stdout
- exec $CTMSW/ctm_smail -m $CTMmaxmsg -c $CTMmaxctm $CTMdest/${nm}.gz $CTMmail >&@ stdout
- if {$CTMqueue != "" && $CTMqueuemail != ""} {
- puts "Queueing delta"
- flush stdout
- exec $CTMSW/ctm_smail -m $CTMmaxmsg -c $CTMmaxctm -q $CTMqueue $CTMdest/${nm}.gz $CTMqueuemail >&@ stdout
- puts "Sending initial two deltas"
- flush stdout
- exec $CTMSW/ctm_dequeue -n 2 $CTMqueue >&@ stdout
- }
- }
- exec echo mailed > $CTMlock
-
- # If we did an absolute delta: stop.
- if {$CTMsuff != ""} break
-
- # Make an absolute delta (!) every 100 deltas
- if {$CTMnbr == 0 || ($CTMnbr % 100)} break
-
- # Make an absolute delta too...
- set CTMref $CTMcopy
- set CTMsuff A
- set CTMcopy ""
- set CTMmail ""
- set CTMqueue ""
- set CTMqueuemail ""
- set CTMapply 0
- set CTMspecial 1
- exec rm -f $CTMlock
-}
-puts "done."
-exec rm -f $CTMlock
diff --git a/usr.sbin/ctm/mkCTM/mkctm.c b/usr.sbin/ctm/mkCTM/mkctm.c
deleted file mode 100644
index d2c73e20809a..000000000000
--- a/usr.sbin/ctm/mkCTM/mkctm.c
+++ /dev/null
@@ -1,597 +0,0 @@
-/* $FreeBSD$ */
-
-/* Still missing:
- *
- * mkctm
- * -B regex Bogus
- * -I regex Ignore
- * -D int Damage
- * -q decrease verbosity
- * -v increase verbosity
- * -l file logfile
- * name cvs-cur
- * prefix src/secure
- * dir1 "Soll"
- * dir2 "Ist"
- *
- * $FreeBSD$
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <sys/wait.h>
-#include <dirent.h>
-#include <regex.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <md5.h>
-#include <err.h>
-#include <paths.h>
-#include <signal.h>
-
-#define DEFAULT_IGNORE "/CVS$|/\\.#|00_TRANS\\.TBL$"
-#define DEFAULT_BOGUS "\\.core$|\\.orig$|\\.rej$|\\.o$"
-regex_t reg_ignore, reg_bogus;
-int flag_ignore, flag_bogus;
-
-int verbose;
-int damage, damage_limit;
-int change;
-
-FILE *logf;
-
-u_long s1_ignored, s2_ignored;
-u_long s1_bogus, s2_bogus;
-u_long s1_wrong, s2_wrong;
-u_long s_new_dirs, s_new_files, s_new_bytes;
-u_long s_del_dirs, s_del_files, s_del_bytes;
-u_long s_files_chg, s_bytes_add, s_bytes_del;
-u_long s_same_dirs, s_same_files, s_same_bytes;
-u_long s_edit_files, s_edit_bytes, s_edit_saves;
-u_long s_sub_files, s_sub_bytes;
-
-void
-Usage(void)
-{
- fprintf(stderr,
- "usage: mkctm [-options] name number timestamp prefix dir1 dir2\n");
- fprintf(stderr, "options:\n");
- fprintf(stderr, "\t\t-B bogus_regexp\n");
- fprintf(stderr, "\t\t-D damage_limit\n");
- fprintf(stderr, "\t\t-I ignore_regexp\n");
- fprintf(stderr, "\t\t-q\n");
- fprintf(stderr, "\t\t-v\n");
-}
-
-void
-print_stat(FILE *fd, char *pre)
-{
- fprintf(fd, "%sNames:\n", pre);
- fprintf(fd, "%s ignore: %5lu ref %5lu target\n",
- pre, s1_ignored, s2_ignored);
- fprintf(fd, "%s bogus: %5lu ref %5lu target\n",
- pre, s1_bogus, s2_bogus);
- fprintf(fd, "%s wrong: %5lu ref %5lu target\n",
- pre, s1_wrong, s2_wrong);
- fprintf(fd, "%sDelta:\n", pre);
- fprintf(fd, "%s new: %5lu dirs %5lu files %9lu plus\n",
- pre, s_new_dirs, s_new_files, s_new_bytes);
- fprintf(fd, "%s del: %5lu dirs %5lu files %9lu minus\n",
- pre, s_del_dirs, s_del_files, s_del_bytes);
- fprintf(fd, "%s chg: %5lu files %9lu plus %9lu minus\n",
- pre, s_files_chg, s_bytes_add, s_bytes_del);
- fprintf(fd, "%s same: %5lu dirs %5lu files %9lu bytes\n",
- pre, s_same_dirs, s_same_files, s_same_bytes);
- fprintf(fd, "%sMethod:\n", pre);
- fprintf(fd, "%s edit: %5lu files %9lu bytes %9lu saved\n",
- pre, s_edit_files, s_edit_bytes, s_edit_saves);
- fprintf(fd, "%s sub: %5lu files %9lu bytes\n",
- pre, s_sub_files, s_sub_bytes);
-
-}
-
-void
-stat_info(int foo)
-{
- signal(SIGINFO, stat_info);
- print_stat(stderr, "INFO: ");
-}
-
-void DoDir(const char *dir1, const char *dir2, const char *name);
-
-static struct stat st;
-static __inline struct stat *
-StatFile(char *name)
-{
- if (lstat(name, &st) < 0)
- err(1, "couldn't stat %s", name);
- return &st;
-}
-
-int
-dirselect(struct dirent *de)
-{
- if (!strcmp(de->d_name, ".")) return 0;
- if (!strcmp(de->d_name, "..")) return 0;
- return 1;
-}
-
-void
-name_stat(const char *pfx, const char *dir, const char *name, struct dirent *de)
-{
- char *buf = alloca(strlen(dir) + strlen(name) +
- strlen(de->d_name) + 3);
- struct stat *st;
-
- strcpy(buf, dir);
- strcat(buf, "/"); strcat(buf, name);
- strcat(buf, "/"); strcat(buf, de->d_name);
- st = StatFile(buf);
- printf("%s %s%s %u %u %o",
- pfx, name, de->d_name,
- st->st_uid, st->st_gid, st->st_mode & ~S_IFMT);
- fprintf(logf, "%s %s%s\n", pfx, name, de->d_name);
- if (verbose > 1) {
- fprintf(stderr, "%s %s%s\n", pfx, name, de->d_name);
- }
-}
-
-void
-Equ(const char *dir1, const char *dir2, const char *name, struct dirent *de)
-{
- if (de->d_type == DT_DIR) {
- char *p = alloca(strlen(name)+strlen(de->d_name)+2);
-
- strcpy(p, name); strcat(p, de->d_name); strcat(p, "/");
- DoDir(dir1, dir2, p);
- s_same_dirs++;
- } else {
- char *buf1 = alloca(strlen(dir1) + strlen(name) +
- strlen(de->d_name) + 3);
- char *buf2 = alloca(strlen(dir2) + strlen(name) +
- strlen(de->d_name) + 3);
- char *m1, md5_1[33], *m2, md5_2[33];
- u_char *p1, *p2;
- int fd1, fd2;
- struct stat s1, s2;
-
- strcpy(buf1, dir1);
- strcat(buf1, "/"); strcat(buf1, name);
- strcat(buf1, "/"); strcat(buf1, de->d_name);
- fd1 = open(buf1, O_RDONLY);
- if(fd1 < 0) { err(3, "%s", buf1); }
- fstat(fd1, &s1);
- strcpy(buf2, dir2);
- strcat(buf2, "/"); strcat(buf2, name);
- strcat(buf2, "/"); strcat(buf2, de->d_name);
- fd2 = open(buf2, O_RDONLY);
- if(fd2 < 0) { err(3, "%s", buf2); }
- fstat(fd2, &s2);
-#if 0
- /* XXX if we could just trust the size to change... */
- if (s1.st_size == s2.st_size) {
- s_same_files++;
- s_same_bytes += s1.st_size;
- close(fd1);
- close(fd2);
- goto finish;
- }
-#endif
- p1=mmap(0, s1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
- if (p1 == (u_char *)MAP_FAILED) { err(3, "%s", buf1); }
- close(fd1);
-
- p2=mmap(0, s2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);
- if (p2 == (u_char *)MAP_FAILED) { err(3, "%s", buf2); }
- close(fd2);
-
- /* If identical, we're done. */
- if((s1.st_size == s2.st_size) && !memcmp(p1, p2, s1.st_size)) {
- s_same_files++;
- s_same_bytes += s1.st_size;
- goto finish;
- }
-
- s_files_chg++;
- change++;
- if (s1.st_size > s2.st_size)
- s_bytes_del += (s1.st_size - s2.st_size);
- else
- s_bytes_add += (s2.st_size - s1.st_size);
-
- m1 = MD5Data(p1, s1.st_size, md5_1);
- m2 = MD5Data(p2, s2.st_size, md5_2);
-
- /* Just a curiosity... */
- if(!strcmp(m1, m2)) {
- if (s1.st_size != s2.st_size)
- fprintf(stderr,
- "Notice: MD5 same for files of diffent size:\n\t%s\n\t%s\n",
- buf1, buf2);
- goto finish;
- }
-
- {
- u_long l = s2.st_size + 2;
- u_char *cmd = alloca(strlen(buf1)+strlen(buf2)+100);
- u_char *ob = malloc(l), *p;
- int j;
- FILE *F;
-
- if (s1.st_size && p1[s1.st_size-1] != '\n') {
- if (verbose > 0)
- fprintf(stderr,
- "last char != \\n in %s\n",
- buf1);
- goto subst;
- }
-
- if (s2.st_size && p2[s2.st_size-1] != '\n') {
- if (verbose > 0)
- fprintf(stderr,
- "last char != \\n in %s\n",
- buf2);
- goto subst;
- }
-
- for (p=p1; p<p1+s1.st_size; p++)
- if (!*p) {
- if (verbose > 0)
- fprintf(stderr,
- "NULL char in %s\n",
- buf1);
- goto subst;
- }
-
- for (p=p2; p<p2+s2.st_size; p++)
- if (!*p) {
- if (verbose > 0)
- fprintf(stderr,
- "NULL char in %s\n",
- buf2);
- goto subst;
- }
-
- strcpy(cmd, "diff -n ");
- strcat(cmd, buf1);
- strcat(cmd, " ");
- strcat(cmd, buf2);
- F = popen(cmd, "r");
- for (j = 1, l = 0; l < s2.st_size; ) {
- j = fread(ob+l, 1, s2.st_size - l, F);
- if (j < 1)
- break;
- l += j;
- continue;
- }
- if (j) {
- l = 0;
- while (EOF != fgetc(F))
- continue;
- }
- pclose(F);
-
- if (l && l < s2.st_size) {
- name_stat("CTMFN", dir2, name, de);
- printf(" %s %s %d\n", m1, m2, (unsigned)l);
- fwrite(ob, 1, l, stdout);
- putchar('\n');
- s_edit_files++;
- s_edit_bytes += l;
- s_edit_saves += (s2.st_size - l);
- } else {
- subst:
- name_stat("CTMFS", dir2, name, de);
- printf(" %s %s %u\n", m1, m2, (unsigned)s2.st_size);
- fwrite(p2, 1, s2.st_size, stdout);
- putchar('\n');
- s_sub_files++;
- s_sub_bytes += s2.st_size;
- }
- free(ob);
- }
- finish:
- munmap(p1, s1.st_size);
- munmap(p2, s2.st_size);
- }
-}
-
-void
-Add(const char *dir1, const char *dir2, const char *name, struct dirent *de)
-{
- change++;
- if (de->d_type == DT_DIR) {
- char *p = alloca(strlen(name)+strlen(de->d_name)+2);
- strcpy(p, name); strcat(p, de->d_name); strcat(p, "/");
- name_stat("CTMDM", dir2, name, de);
- putchar('\n');
- s_new_dirs++;
- DoDir(dir1, dir2, p);
- } else if (de->d_type == DT_REG) {
- char *buf2 = alloca(strlen(dir2) + strlen(name) +
- strlen(de->d_name) + 3);
- char *m2, md5_2[33];
- u_char *p1;
- struct stat st;
- int fd1;
-
- strcpy(buf2, dir2);
- strcat(buf2, "/"); strcat(buf2, name);
- strcat(buf2, "/"); strcat(buf2, de->d_name);
- fd1 = open(buf2, O_RDONLY);
- if (fd1 < 0) { err(3, "%s", buf2); }
- fstat(fd1, &st);
- p1=mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
- if (p1 == (u_char *)MAP_FAILED) { err(3, "%s", buf2); }
- close(fd1);
- m2 = MD5Data(p1, st.st_size, md5_2);
- name_stat("CTMFM", dir2, name, de);
- printf(" %s %u\n", m2, (unsigned)st.st_size);
- fwrite(p1, 1, st.st_size, stdout);
- putchar('\n');
- munmap(p1, st.st_size);
- s_new_files++;
- s_new_bytes += st.st_size;
- }
-}
-
-void
-Del (const char *dir1, const char *dir2, const char *name, struct dirent *de)
-{
- damage++;
- change++;
- if (de->d_type == DT_DIR) {
- char *p = alloca(strlen(name)+strlen(de->d_name)+2);
- strcpy(p, name); strcat(p, de->d_name); strcat(p, "/");
- DoDir(dir1, dir2, p);
- printf("CTMDR %s%s\n", name, de->d_name);
- fprintf(logf, "CTMDR %s%s\n", name, de->d_name);
- if (verbose > 1) {
- fprintf(stderr, "CTMDR %s%s\n", name, de->d_name);
- }
- s_del_dirs++;
- } else if (de->d_type == DT_REG) {
- char *buf1 = alloca(strlen(dir1) + strlen(name) +
- strlen(de->d_name) + 3);
- char *m1, md5_1[33];
- strcpy(buf1, dir1);
- strcat(buf1, "/"); strcat(buf1, name);
- strcat(buf1, "/"); strcat(buf1, de->d_name);
- m1 = MD5File(buf1, md5_1);
- printf("CTMFR %s%s %s\n", name, de->d_name, m1);
- fprintf(logf, "CTMFR %s%s %s\n", name, de->d_name, m1);
- if (verbose > 1) {
- fprintf(stderr, "CTMFR %s%s\n", name, de->d_name);
- }
- s_del_files++;
- s_del_bytes += StatFile(buf1)->st_size;
- }
-}
-
-void
-GetNext(int *i, int *n, struct dirent **nl, const char *dir, const char *name, u_long *ignored, u_long *bogus, u_long *wrong)
-{
- char buf[BUFSIZ];
- char buf1[BUFSIZ];
-
- for (;;) {
- for (;;) {
- (*i)++;
- if (*i >= *n)
- return;
- strcpy(buf1, name);
- if (buf1[strlen(buf1)-1] != '/')
- strcat(buf1, "/");
- strcat(buf1, nl[*i]->d_name);
- if (flag_ignore &&
- !regexec(&reg_ignore, buf1, 0, 0, 0)) {
- (*ignored)++;
- fprintf(logf, "Ignore %s\n", buf1);
- if (verbose > 2) {
- fprintf(stderr, "Ignore %s\n", buf1);
- }
- } else if (flag_bogus &&
- !regexec(&reg_bogus, buf1, 0, 0, 0)) {
- (*bogus)++;
- fprintf(logf, "Bogus %s\n", buf1);
- fprintf(stderr, "Bogus %s\n", buf1);
- damage++;
- } else {
- *buf = 0;
- if (*dir != '/')
- strcat(buf, "/");
- strcat(buf, dir);
- if (buf[strlen(buf)-1] != '/')
- strcat(buf, "/");
- strcat(buf, buf1);
- break;
- }
- free(nl[*i]); nl[*i] = 0;
- }
- /* If the filesystem didn't tell us, find type */
- if (nl[*i]->d_type == DT_UNKNOWN)
- nl[*i]->d_type = IFTODT(StatFile(buf)->st_mode);
- if (nl[*i]->d_type == DT_REG || nl[*i]->d_type == DT_DIR)
- break;
- (*wrong)++;
- if (verbose > 0)
- fprintf(stderr, "Wrong %s\n", buf);
- free(nl[*i]); nl[*i] = 0;
- }
-}
-
-void
-DoDir(const char *dir1, const char *dir2, const char *name)
-{
- int i1, i2, n1, n2, i;
- struct dirent **nl1, **nl2;
- char *buf1 = alloca(strlen(dir1) + strlen(name) + 4);
- char *buf2 = alloca(strlen(dir2) + strlen(name) + 4);
-
- strcpy(buf1, dir1); strcat(buf1, "/"); strcat(buf1, name);
- strcpy(buf2, dir2); strcat(buf2, "/"); strcat(buf2, name);
- n1 = scandir(buf1, &nl1, dirselect, alphasort);
- n2 = scandir(buf2, &nl2, dirselect, alphasort);
- i1 = i2 = -1;
- GetNext(&i1, &n1, nl1, dir1, name, &s1_ignored, &s1_bogus, &s1_wrong);
- GetNext(&i2, &n2, nl2, dir2, name, &s2_ignored, &s2_bogus, &s2_wrong);
- for (;i1 < n1 || i2 < n2;) {
-
- if (damage_limit && damage > damage_limit)
- break;
-
- /* Get next item from list 1 */
- if (i1 < n1 && !nl1[i1])
- GetNext(&i1, &n1, nl1, dir1, name,
- &s1_ignored, &s1_bogus, &s1_wrong);
-
- /* Get next item from list 2 */
- if (i2 < n2 && !nl2[i2])
- GetNext(&i2, &n2, nl2, dir2, name,
- &s2_ignored, &s2_bogus, &s2_wrong);
-
- if (i1 >= n1 && i2 >= n2) {
- /* Done */
- break;
- } else if (i1 >= n1 && i2 < n2) {
- /* end of list 1, add anything left on list 2 */
- Add(dir1, dir2, name, nl2[i2]);
- free(nl2[i2]); nl2[i2] = 0;
- } else if (i1 < n1 && i2 >= n2) {
- /* end of list 2, delete anything left on list 1 */
- Del(dir1, dir2, name, nl1[i1]);
- free(nl1[i1]); nl1[i1] = 0;
- } else if (!(i = strcmp(nl1[i1]->d_name, nl2[i2]->d_name))) {
- /* Identical names */
- if (nl1[i1]->d_type == nl2[i2]->d_type) {
- /* same type */
- Equ(dir1, dir2, name, nl1[i1]);
- } else {
- /* different types */
- Del(dir1, dir2, name, nl1[i1]);
- Add(dir1, dir2, name, nl2[i2]);
- }
- free(nl1[i1]); nl1[i1] = 0;
- free(nl2[i2]); nl2[i2] = 0;
- } else if (i < 0) {
- /* Something extra in list 1, delete it */
- Del(dir1, dir2, name, nl1[i1]);
- free(nl1[i1]); nl1[i1] = 0;
- } else {
- /* Something extra in list 2, add it */
- Add(dir1, dir2, name, nl2[i2]);
- free(nl2[i2]); nl2[i2] = 0;
- }
- }
- if (n1 >= 0)
- free(nl1);
- if (n2 >= 0)
- free(nl2);
-}
-
-int
-main(int argc, char **argv)
-{
- int i;
-
- setbuf(stderr, NULL);
-
-#if 0
- if (regcomp(&reg_bogus, DEFAULT_BOGUS, REG_EXTENDED | REG_NEWLINE))
- /* XXX use regerror to explain it */
- errx(1, "default regular expression argument to -B is botched");
- flag_bogus = 1;
-
- if (regcomp(&reg_ignore, DEFAULT_IGNORE, REG_EXTENDED | REG_NEWLINE))
- /* XXX use regerror to explain it */
- errx(1, "default regular expression argument to -I is botched");
- flag_ignore = 1;
-#endif
-
- while ((i = getopt(argc, argv, "D:I:B:l:qv")) != -1)
- switch (i) {
- case 'D':
- damage_limit = strtol(optarg, 0, 0);
- if (damage_limit < 0)
- errx(1, "damage limit must be positive");
- break;
- case 'I':
- if (flag_ignore)
- regfree(&reg_ignore);
- flag_ignore = 0;
- if (!*optarg)
- break;
- if (regcomp(&reg_ignore, optarg,
- REG_EXTENDED | REG_NEWLINE))
- /* XXX use regerror to explain it */
- errx(1, "regular expression argument to -I is botched");
- flag_ignore = 1;
- break;
- case 'B':
- if (flag_bogus)
- regfree(&reg_bogus);
- flag_bogus = 0;
- if (!*optarg)
- break;
- if (regcomp(&reg_bogus, optarg,
- REG_EXTENDED | REG_NEWLINE))
- /* XXX use regerror to explain it */
- errx(1, "regular expression argument to -B is botched");
- flag_bogus = 1;
- break;
- case 'l':
- logf = fopen(optarg, "w");
- if (!logf)
- err(1, "%s", optarg);
- setlinebuf(logf);
- break;
- case 'q':
- verbose--;
- break;
- case 'v':
- verbose++;
- break;
- case '?':
- default:
- Usage();
- return (1);
- }
- argc -= optind;
- argv += optind;
-
- if (!logf)
- logf = fopen(_PATH_DEVNULL, "w");
-
- setbuf(stdout, 0);
-
- if (argc != 6) {
- Usage();
- return (1);
- }
-
- signal(SIGINFO, stat_info);
-
- fprintf(stderr, "CTM_BEGIN 2.0 %s %s %s %s\n",
- argv[0], argv[1], argv[2], argv[3]);
- fprintf(logf, "CTM_BEGIN 2.0 %s %s %s %s\n",
- argv[0], argv[1], argv[2], argv[3]);
- printf("CTM_BEGIN 2.0 %s %s %s %s\n",
- argv[0], argv[1], argv[2], argv[3]);
- DoDir(argv[4], argv[5], "");
- if (damage_limit && damage > damage_limit) {
- print_stat(stderr, "DAMAGE: ");
- errx(1, "damage of %d would exceed %d files",
- damage, damage_limit);
- } else if (change < 2) {
- errx(4, "no changes");
- } else {
- printf("CTM_END ");
- fprintf(logf, "CTM_END\n");
- print_stat(stderr, "END: ");
- }
- exit(0);
-}