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