Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164811454
D17935.id50251.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
147 KB
Referenced Files
None
Subscribers
None
D17935.id50251.diff
View Options
Index: ObsoleteFiles.inc
===================================================================
--- ObsoleteFiles.inc
+++ ObsoleteFiles.inc
@@ -38,6 +38,16 @@
# xargs -n1 | sort | uniq -d;
# done
+# 20181110: Migration of CTM to ports
+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
# 20181030: malloc_domain(9) KPI change
OLD_FILES+=share/man/man9/malloc_domain.9.gz
# 20181026: joy(4) removal
Index: share/man/man5/src.conf.5
===================================================================
--- share/man/man5/src.conf.5
+++ share/man/man5/src.conf.5
@@ -469,10 +469,6 @@
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
Index: tools/build/mk/OptionalObsoleteFiles.inc
===================================================================
--- tools/build/mk/OptionalObsoleteFiles.inc
+++ tools/build/mk/OptionalObsoleteFiles.inc
@@ -1532,18 +1532,6 @@
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
Index: tools/build/options/WITHOUT_CTM
===================================================================
--- tools/build/options/WITHOUT_CTM
+++ tools/build/options/WITHOUT_CTM
@@ -1,4 +0,0 @@
-.\" $FreeBSD$
-Set to not build
-.Xr ctm 1
-and related utilities.
Index: usr.sbin/Makefile
===================================================================
--- usr.sbin/Makefile
+++ usr.sbin/Makefile
@@ -122,7 +122,6 @@
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
Index: usr.sbin/ctm/Makefile
===================================================================
--- usr.sbin/ctm/Makefile
+++ usr.sbin/ctm/Makefile
@@ -1,5 +0,0 @@
-# $FreeBSD$
-
-SUBDIR= ctm ctm_rmail ctm_smail ctm_dequeue
-
-.include <bsd.subdir.mk>
Index: usr.sbin/ctm/Makefile.inc
===================================================================
--- usr.sbin/ctm/Makefile.inc
+++ usr.sbin/ctm/Makefile.inc
@@ -1,5 +0,0 @@
-# $FreeBSD$
-
-.if exists(${.CURDIR:H:H}/Makefile.inc)
-.include "${.CURDIR:H:H}/Makefile.inc"
-.endif
Index: usr.sbin/ctm/README
===================================================================
--- usr.sbin/ctm/README
+++ usr.sbin/ctm/README
@@ -1,89 +0,0 @@
-# ----------------------------------------------------------------------------
-# "THE BEER-WARE LICENSE" (Revision 42):
-# <phk@FreeBSD.org> 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 <CTM@FreeBSD.org> 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
Index: usr.sbin/ctm/ctm/Makefile
===================================================================
--- usr.sbin/ctm/ctm/Makefile
+++ usr.sbin/ctm/ctm/Makefile
@@ -1,24 +0,0 @@
-# ----------------------------------------------------------------------------
-# "THE BEER-WARE LICENSE" (Revision 42):
-# <phk@FreeBSD.org> 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>
Index: usr.sbin/ctm/ctm/Makefile.depend
===================================================================
--- usr.sbin/ctm/ctm/Makefile.depend
+++ usr.sbin/ctm/ctm/Makefile.depend
@@ -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
Index: usr.sbin/ctm/ctm/ctm.h
===================================================================
--- usr.sbin/ctm/ctm/ctm.h
+++ usr.sbin/ctm/ctm/ctm.h
@@ -1,163 +0,0 @@
-/*
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.org> 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);
Index: usr.sbin/ctm/ctm/ctm.1
===================================================================
--- usr.sbin/ctm/ctm/ctm.1
+++ usr.sbin/ctm/ctm/ctm.1
@@ -1,330 +0,0 @@
-.\" ----------------------------------------------------------------------------
-.\" "THE BEER-WARE LICENSE" (Revision 42):
-.\" <joerg@FreeBSD.org> 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 <phk@FreeBSD.org>
-.\"
-.\" $FreeBSD$
-.\"
-.Dd April 14, 2016
-.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 ctm@FreeBSD.org.
-.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 .
-.Sh AUTHORS
-.An -nosplit
-The CTM system has been designed and implemented by
-.An Poul-Henning Kamp Aq Mt phk@FreeBSD.org .
-.Pp
-.An Joerg Wunsch Aq Mt joerg@FreeBSD.org
-wrote this man-page.
Index: usr.sbin/ctm/ctm/ctm.5
===================================================================
--- usr.sbin/ctm/ctm/ctm.5
+++ usr.sbin/ctm/ctm/ctm.5
@@ -1,182 +0,0 @@
-.\" ----------------------------------------------------------------------------
-.\" "THE BEER-WARE LICENSE" (Revision 42):
-.\" <joerg@FreeBSD.org> 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 <phk@FreeBSD.org>
-.\"
-.\" $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 phk@FreeBSD.org .
-.Pp
-.An Joerg Wunsch Aq Mt joerg@FreeBSD.org
-wrote this man-page.
Index: usr.sbin/ctm/ctm/ctm.c
===================================================================
--- usr.sbin/ctm/ctm/ctm.c
+++ usr.sbin/ctm/ctm/ctm.c
@@ -1,333 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.org> 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;
- }
- 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;
-}
Index: usr.sbin/ctm/ctm/ctm_ed.c
===================================================================
--- usr.sbin/ctm/ctm/ctm_ed.c
+++ usr.sbin/ctm/ctm/ctm_ed.c
@@ -1,116 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.org> 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;
-}
Index: usr.sbin/ctm/ctm/ctm_input.c
===================================================================
--- usr.sbin/ctm/ctm/ctm_input.c
+++ usr.sbin/ctm/ctm/ctm_input.c
@@ -1,136 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.org> 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);
-}
Index: usr.sbin/ctm/ctm/ctm_pass1.c
===================================================================
--- usr.sbin/ctm/ctm/ctm_pass1.c
+++ usr.sbin/ctm/ctm/ctm_pass1.c
@@ -1,254 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.org> 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", ¤t);
- 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);
-}
Index: usr.sbin/ctm/ctm/ctm_pass2.c
===================================================================
--- usr.sbin/ctm/ctm/ctm_pass2.c
+++ usr.sbin/ctm/ctm/ctm_pass2.c
@@ -1,303 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.org> 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;
-}
Index: usr.sbin/ctm/ctm/ctm_pass3.c
===================================================================
--- usr.sbin/ctm/ctm/ctm_pass3.c
+++ usr.sbin/ctm/ctm/ctm_pass3.c
@@ -1,297 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.org> 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;
-}
Index: usr.sbin/ctm/ctm/ctm_passb.c
===================================================================
--- usr.sbin/ctm/ctm/ctm_passb.c
+++ usr.sbin/ctm/ctm/ctm_passb.c
@@ -1,144 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <koshy@india.hp.com> 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;
-}
Index: usr.sbin/ctm/ctm/ctm_syntax.c
===================================================================
--- usr.sbin/ctm/ctm/ctm_syntax.c
+++ usr.sbin/ctm/ctm/ctm_syntax.c
@@ -1,69 +0,0 @@
-/*-
- * SPDX-License-Identifier: Beerware
- *
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.org> 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} };
Index: usr.sbin/ctm/ctm_dequeue/Makefile
===================================================================
--- usr.sbin/ctm/ctm_dequeue/Makefile
+++ usr.sbin/ctm/ctm_dequeue/Makefile
@@ -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>
Index: usr.sbin/ctm/ctm_dequeue/Makefile.depend
===================================================================
--- usr.sbin/ctm/ctm_dequeue/Makefile.depend
+++ usr.sbin/ctm/ctm_dequeue/Makefile.depend
@@ -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
Index: usr.sbin/ctm/ctm_dequeue/ctm_dequeue.c
===================================================================
--- usr.sbin/ctm/ctm_dequeue/ctm_dequeue.c
+++ usr.sbin/ctm/ctm_dequeue/ctm_dequeue.c
@@ -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);
-}
Index: usr.sbin/ctm/ctm_rmail/Makefile
===================================================================
--- usr.sbin/ctm/ctm_rmail/Makefile
+++ usr.sbin/ctm/ctm_rmail/Makefile
@@ -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>
Index: usr.sbin/ctm/ctm_rmail/Makefile.depend
===================================================================
--- usr.sbin/ctm/ctm_rmail/Makefile.depend
+++ usr.sbin/ctm/ctm_rmail/Makefile.depend
@@ -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
Index: usr.sbin/ctm/ctm_rmail/ctm_rmail.1
===================================================================
--- usr.sbin/ctm/ctm_rmail/ctm_rmail.1
+++ usr.sbin/ctm/ctm_rmail/ctm_rmail.1
@@ -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: real_dude@wherever.you.like
-.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 ctm@FreeBSD.org.
-.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 mckay@FreeBSD.org
Index: usr.sbin/ctm/ctm_rmail/ctm_rmail.c
===================================================================
--- usr.sbin/ctm/ctm_rmail/ctm_rmail.c
+++ usr.sbin/ctm/ctm_rmail/ctm_rmail.c
@@ -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;
- }
Index: usr.sbin/ctm/ctm_rmail/error.h
===================================================================
--- usr.sbin/ctm/ctm_rmail/error.h
+++ usr.sbin/ctm/ctm_rmail/error.h
@@ -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);
Index: usr.sbin/ctm/ctm_rmail/error.c
===================================================================
--- usr.sbin/ctm/ctm_rmail/error.c
+++ usr.sbin/ctm/ctm_rmail/error.c
@@ -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);
- }
Index: usr.sbin/ctm/ctm_rmail/options.h
===================================================================
--- usr.sbin/ctm/ctm_rmail/options.h
+++ usr.sbin/ctm/ctm_rmail/options.h
@@ -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; \
- }
Index: usr.sbin/ctm/ctm_smail/Makefile
===================================================================
--- usr.sbin/ctm/ctm_smail/Makefile
+++ usr.sbin/ctm/ctm_smail/Makefile
@@ -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>
Index: usr.sbin/ctm/ctm_smail/Makefile.depend
===================================================================
--- usr.sbin/ctm/ctm_smail/Makefile.depend
+++ usr.sbin/ctm/ctm_smail/Makefile.depend
@@ -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
Index: usr.sbin/ctm/ctm_smail/ctm_smail.c
===================================================================
--- usr.sbin/ctm/ctm_smail/ctm_smail.c
+++ usr.sbin/ctm/ctm_smail/ctm_smail.c
@@ -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);
- }
Index: usr.sbin/ctm/mkCTM/Makefile
===================================================================
--- usr.sbin/ctm/mkCTM/Makefile
+++ usr.sbin/ctm/mkCTM/Makefile
@@ -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>
Index: usr.sbin/ctm/mkCTM/ctm_conf.cvs-cur
===================================================================
--- usr.sbin/ctm/mkCTM/ctm_conf.cvs-cur
+++ usr.sbin/ctm/mkCTM/ctm_conf.cvs-cur
@@ -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 ctm-cvs-cur-fast@freebsd.org
-set CTMqueuemail ctm-cvs-cur@freebsd.org
-set CTMqueue /home/ctm/queue/ctm-cvs-cur
Index: usr.sbin/ctm/mkCTM/ctm_conf.ports-cur
===================================================================
--- usr.sbin/ctm/mkCTM/ctm_conf.ports-cur
+++ usr.sbin/ctm/mkCTM/ctm_conf.ports-cur
@@ -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 ctm-ports-cur@freebsd.org
Index: usr.sbin/ctm/mkCTM/ctm_conf.smp-cur
===================================================================
--- usr.sbin/ctm/mkCTM/ctm_conf.smp-cur
+++ usr.sbin/ctm/mkCTM/ctm_conf.smp-cur
@@ -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 smp-cvs-cur@freebsd.org
Index: usr.sbin/ctm/mkCTM/ctm_conf.src-cur
===================================================================
--- usr.sbin/ctm/mkCTM/ctm_conf.src-cur
+++ usr.sbin/ctm/mkCTM/ctm_conf.src-cur
@@ -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 ctm-src-cur-fast@freebsd.org
-set CTMqueue /home/ctm/queue/ctm-src-cur
-set CTMqueuemail ctm-src-cur@freebsd.org
Index: usr.sbin/ctm/mkCTM/ctm_conf.src-special
===================================================================
--- usr.sbin/ctm/mkCTM/ctm_conf.src-special
+++ usr.sbin/ctm/mkCTM/ctm_conf.src-special
@@ -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
Index: usr.sbin/ctm/mkCTM/dequeue
===================================================================
--- usr.sbin/ctm/mkCTM/dequeue
+++ usr.sbin/ctm/mkCTM/dequeue
@@ -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
Index: usr.sbin/ctm/mkCTM/mkCTM
===================================================================
--- usr.sbin/ctm/mkCTM/mkCTM
+++ usr.sbin/ctm/mkCTM/mkCTM
@@ -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
Index: usr.sbin/ctm/mkCTM/mkctm.c
===================================================================
--- usr.sbin/ctm/mkCTM/mkctm.c
+++ usr.sbin/ctm/mkCTM/mkctm.c
@@ -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(®_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(®_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(®_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(®_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(®_ignore);
- flag_ignore = 0;
- if (!*optarg)
- break;
- if (regcomp(®_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(®_bogus);
- flag_bogus = 0;
- if (!*optarg)
- break;
- if (regcomp(®_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);
-}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Aug 5, 4:09 AM (20 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35992522
Default Alt Text
D17935.id50251.diff (147 KB)
Attached To
Mode
D17935: Remove CTM from 13-CURRENT
Attached
Detach File
Event Timeline
Log In to Comment