Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 May 2014 18:54:22 GMT
From:      Michael Graziano <mikeg@bsd-box.net>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   ports/190120: Staging (and other misc. updates) for sysutils/radmind
Message-ID:  <201405221854.s4MIsM88029312@cgiserv.freebsd.org>
Resent-Message-ID: <201405221900.s4MJ01vF011345@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         190120
>Category:       ports
>Synopsis:       Staging (and other misc. updates) for sysutils/radmind
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          maintainer-update
>Submitter-Id:   current-users
>Arrival-Date:   Thu May 22 19:00:01 UTC 2014
>Closed-Date:
>Last-Modified:
>Originator:     Michael Graziano
>Release:        RELENG_9_1
>Organization:
>Environment:
FreeBSD SYSBUILDER.dev.premierheart.com 9.1-RELEASE-p12 FreeBSD 9.1-RELEASE-p12 #3 r265198: Thu May  1 17:14:50 EDT 2014     root@SYSBUILDER.dev.premierheart.com:/usr/obj/usr/src/sys/ph-amd64  amd64
>Description:
The attached patch converts sysutils/radmind for staging.
Staging QA tests pass and packaging appears to be working correctly for both root and non-root users.


This patch also removes the "ignore timestamps" option (subtly broken and no longer used in my environment so I can't validate it) and adds upstream bug fixes through 2012-05-22 which are not currently in the distfiles.

Recommend applying this patch with "patch -E" to remove dead items from the files directory which are now contained in the rollup patch.
>How-To-Repeat:

>Fix:
Patch attached

Patch attached with submission follows:

diff -ruN ./Makefile ./Makefile
--- ./Makefile	2014-05-22 14:34:26.000000000 -0400
+++ ./Makefile	2014-05-22 14:23:44.000000000 -0400
@@ -3,7 +3,7 @@
 
 PORTNAME=	radmind
 PORTVERSION=	1.14.1
-PORTREVISION=	2012032001
+PORTREVISION=	2014052201
 CATEGORIES=	sysutils
 MASTER_SITES=	SF
 MASTER_SITE_SUBDIR=${PORTNAME}/${PORTNAME}/${PORTNAME}-${PORTVERSION}
@@ -27,35 +27,33 @@
 PLIST_SUB=	RADMIND_BASE_DIR=${RADMIND_BASE_DIR} RADMINUSER=${RADMINUSER}
 SUB_FILES+=	pkg-install pkg-message
 
-MAN1=		fsdiff.1 ktcheck.1 lapply.1 lcksum.1 lcreate.1 lfdiff.1 \
-		lmerge.1 lsort.1 twhich.1 rash.1 repo.1
-MAN5=		applefile.5
-MAN8=		radmind.8
 DOCS=		COPYRIGHT README SPEC
 
-OPTIONS_DEFINE=	IGNORE_TIMESTAMPS DOCS
+OPTIONS_DEFINE=	DOCS
 IGNORE_TIMESTAMPS_DESC=	Add '-t' option to fsdiff
 
-NO_STAGE=	yes
 .include <bsd.port.options.mk>
 
-.if ${PORT_OPTIONS:MIGNORE_TIMESTAMPS}
-EXTRA_PATCHES+=	${FILESDIR}/optpatch-ignore_timestamps
-.endif
-
 post-install:
-# Ugly hack to remove generated man pages
+	# Ugly hack to remove generated man pages
 	${RM} -rf ${WRKSRC}/tmp
 
-.if ${PORT_OPTIONS:MDOCS}
-	${MKDIR} ${DOCSDIR}
-	cd ${WRKSRC} && ${INSTALL_DATA} ${DOCS} ${DOCSDIR}
-.endif
-	${CP} ${FILESDIR}/config.sample ${RADMIND_BASE_DIR}/config.sample
-	@if [ ! -f ${RADMIND_BASE_DIR}/config ]; then \
-		${CP} -p ${RADMIND_BASE_DIR}/config.sample ${RADMIND_BASE_DIR}/config ; \
-	fi
-	@${CHOWN} -R ${RADMINUSER}:${RADMINUSER} ${RADMIND_BASE_DIR}
-	@${CAT} ${PKGMESSAGE}
+	# Port's Docs (Copyright & wire protocol info) 
+	${MKDIR} ${STAGEDIR}${DOCSDIR}
+	cd ${WRKSRC} && ${INSTALL_DATA} ${DOCS} ${STAGEDIR}${DOCSDIR}
+
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/cert
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/client
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/command
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/file
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/postapply
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/preapply
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/special
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/tmp
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/tmp/file
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/tmp/transcript
+	${MKDIR} ${STAGEDIR}${RADMIND_BASE_DIR}/transcript
+	${CP}    ${FILESDIR}/config.sample ${STAGEDIR}${RADMIND_BASE_DIR}/config.sample
 
 .include <bsd.port.mk>
diff -ruN ./files/optpatch-ignore_timestamps ./files/optpatch-ignore_timestamps
--- ./files/optpatch-ignore_timestamps	2014-05-22 14:34:26.000000000 -0400
+++ ./files/optpatch-ignore_timestamps	1969-12-31 19:00:00.000000000 -0500
@@ -1,94 +0,0 @@
---- fsdiff.c.orig
-+++ fsdiff.c
-@@ -33,6 +33,7 @@ int		dotfd;
- int		lastpercent = -1;
- int		case_sensitive = 1;
- int		tran_format = -1; 
-+int		ignore_timestamps = 0;
- extern int	exclude_warnings;
- const EVP_MD    *md;
- 
-@@ -266,7 +267,7 @@ main( int argc, char **argv )
-     cksum = 0;
-     outtran = stdout;
- 
--    while (( c = getopt( argc, argv, "%1ACc:IK:o:VvW" )) != EOF ) {
-+    while (( c = getopt( argc, argv, "%1ACc:IK:o:tVvW" )) != EOF ) {
- 	switch( c ) {
- 	case '%':
- 	case 'v':
-@@ -320,6 +321,10 @@ main( int argc, char **argv )
- 	    exclude_warnings = 1;
- 	    break;
- 
-+	case 't':		/* ignore files for which only the time has changed */
-+	    ignore_timestamps = 1;
-+	break;
-+
- 	case '?':
- 	    printf( "bad %c\n", c );
- 	    errflag++;
-
---- man/fsdiff.1.orig
-+++ man/fsdiff.1
-@@ -11,7 +11,7 @@
- |
- .B -1
- } [
--.BI -IVW
-+.BI -IVWt
- ] [
- .BI \-K\  command
- ] [
-@@ -312,6 +312,9 @@ order of preference and then exits.
- prints a warning to the standard error when encountering an object
- matching an exclude pattern.
- .sp
-+.TP 19
-+.B \-t
-+ignores files where only the timestamp has changed.
- .SH FILES
- .TP 19
- .B _RADMIND_COMMANDFILE
-
---- transcript.c.orig
-+++ transcript.c
-@@ -38,6 +38,7 @@ static struct transcript	*prev_tran = NULL;
- extern int			edit_path;
- extern int			case_sensitive;
- extern int			tran_format;
-+extern int			ignore_timestamps;
- static char			*kdir;
- static struct list		*kfile_list;
- struct list			*special_list;
-@@ -45,6 +46,7 @@ struct list			*exclude_list;
- 
- char				*path_prefix = NULL;
- int				edit_path;
-+int				ignore_timestamps;
- int				skip;
- int				cksum;
- int				fs_minus;
-@@ -544,14 +546,16 @@ t_compare( struct pathinfo *fs, struct transcript *tran )
- 		    t_print( fs, tran, PR_DOWNLOAD );
- 		    break;
- 		}
--	    } else if ( fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime ) {
--		t_print( fs, tran, PR_DOWNLOAD );
--		break;
-+	    } else if ( ignore_timestamps == 0 &&
-+			fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime) {
-+		    t_print( fs, tran, PR_DOWNLOAD );
-+		    break;
- 	    }
- 
--	    if ( fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime ) {
--		t_print( fs, tran, PR_STATUS );
--		break;
-+	    if ( ignore_timestamps == 0 &&
-+		 fs->pi_stat.st_mtime != tran->t_pinfo.pi_stat.st_mtime ) {
-+		    t_print( fs, tran, PR_STATUS );
-+		    break;
- 	    }
- 	}
- 
diff -ruN ./files/patch-.gitignore ./files/patch-.gitignore
--- ./files/patch-.gitignore	2014-05-22 14:34:26.000000000 -0400
+++ ./files/patch-.gitignore	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
---- ./.gitignore.orig	2010-12-12 22:42:49.000000000 -0500
-+++ ./.gitignore	2012-03-20 14:37:54.000000000 -0400
-@@ -10,12 +10,8 @@
- config.log
- config.status
- 
--# External Libraries #
--######################
--libsnet
--
--# Comiled Files #
--#################
-+# Compiled Files #
-+##################
- *.o
- fsdiff
- ktcheck
diff -ruN ./files/patch-20140522 ./files/patch-20140522
--- ./files/patch-20140522	1969-12-31 19:00:00.000000000 -0500
+++ ./files/patch-20140522	2014-05-22 14:34:49.000000000 -0400
@@ -0,0 +1,1412 @@
+diff --git a/.gitignore b/.gitignore
+index fc33886..dc49f11 100644
+--- ./.gitignore
++++ ./.gitignore
+@@ -10,12 +10,8 @@ config.h
+ config.log
+ config.status
+ 
+-# External Libraries #
+-######################
+-libsnet
+-
+-# Comiled Files #
+-#################
++# Compiled Files #
++##################
+ *.o
+ fsdiff
+ ktcheck
+diff --git a/.gitmodules b/.gitmodules
+new file mode 100644
+index 0000000..3ebdb4a
+--- /dev/null
++++ ./.gitmodules
+@@ -0,0 +1,3 @@
++[submodule "libsnet"]
++	path = libsnet
++	url = git://libsnet.git.sourceforge.net/gitroot/libsnet/libsnet
+diff --git a/Makefile.in b/Makefile.in
+index e45ecfd..8b0bef8 100644
+--- ./Makefile.in
++++ ./Makefile.in
+@@ -204,37 +204,37 @@ tls.o : tls.c
+ radmind : libsnet/libsnet.la ${RADMIND_OBJ} Makefile
+ 	${CC} ${CFLAGS} -o radmind ${RADMIND_OBJ} ${LDFLAGS}
+ 
+-fsdiff : ${FSDIFF_OBJ}
++fsdiff : libsnet/libsnet.la ${FSDIFF_OBJ}
+ 	${CC} ${CFLAGS} -o fsdiff ${FSDIFF_OBJ} ${LDFLAGS}
+ 
+-ktcheck: ${KTCHECK_OBJ}
++ktcheck: libsnet/libsnet.la ${KTCHECK_OBJ}
+ 	${CC} ${CFLAGS} -o ktcheck ${KTCHECK_OBJ} ${LDFLAGS}
+ 
+-lapply: ${LAPPLY_OBJ}
++lapply: libsnet/libsnet.la ${LAPPLY_OBJ}
+ 	${CC} ${CFLAGS} -o lapply ${LAPPLY_OBJ} ${LDFLAGS}
+ 
+-lcksum: ${LCKSUM_OBJ}
++lcksum: libsnet/libsnet.la ${LCKSUM_OBJ}
+ 	${CC} ${CFLAGS} -o lcksum ${LCKSUM_OBJ} ${LDFLAGS}
+ 
+-lcreate: ${LCREATE_OBJ}
++lcreate: libsnet/libsnet.la ${LCREATE_OBJ}
+ 	${CC} ${CFLAGS} -o lcreate ${LCREATE_OBJ} ${LDFLAGS}
+ 
+-lmerge: ${LMERGE_OBJ}
++lmerge: libsnet/libsnet.la ${LMERGE_OBJ}
+ 	${CC} ${CFLAGS} -o lmerge ${LMERGE_OBJ} ${LDFLAGS}
+ 
+-lfdiff: ${LFDIFF_OBJ}
++lfdiff: libsnet/libsnet.la ${LFDIFF_OBJ}
+ 	${CC} ${CFLAGS} -o lfdiff ${LFDIFF_OBJ} ${LDFLAGS}
+ 
+-repo : ${REPO_OBJ}
++repo: libsnet/libsnet.la ${REPO_OBJ}
+ 	${CC} ${CFLAGS} -o repo ${REPO_OBJ} ${LDFLAGS}
+ 
+ t2pkg: ${T2PKG_OBJ}
+ 	${CC} ${CFLAGS} -o t2pkg ${T2PKG_OBJ} ${LDFLAGS}
+ 
+-twhich: ${TWHICH_OBJ}
++twhich: libsnet/libsnet.la ${TWHICH_OBJ}
+ 	${CC} ${CFLAGS} -o twhich ${TWHICH_OBJ} ${LDFLAGS}
+ 
+-lsort: ${LSORT_OBJ}
++lsort: libsnet/libsnet.la ${LSORT_OBJ}
+ 	${CC} ${CFLAGS} -o lsort ${LSORT_OBJ} ${LDFLAGS}
+ 
+ FRC :
+diff --git a/README b/README
+index bc034ca..4e7e03b 100644
+--- ./README
++++ ./README
+@@ -72,25 +72,25 @@ for the kerberos header files:
+   % "env CPPFLAGS=-I/usr/kerberos/include ./configure"
+ 
+ -----------------
+-Building from CVS
++Building from git
+ -----------------
+ The Radmind Development Team occasionally asks for help testing a new feature
+ or bug fix. The best way to assist is to download the source code from the
+-CVS repository and build it manually. The following steps will result in
+-a build from CVS.
++git repository and build it manually. The following steps will result in
++a build from git.
+ 
+-1) Download the source from CVS:
++1) Download the source from git:
+ 
+-cvs -d :pserver:anonymous@radmind.cvs.sourceforge.net:/cvsroot/radmind \
+-	checkout radmind
++    git clone git://radmind.git.sourceforge.net/gitroot/radmind/radmind
+ 
+ 2) Move into the new radmind directory:
+ 
+-cd radmind
++    cd radmind
+ 
+-3) Download libsnet[1], the network library Radmind uses:
++3) Checkout all required submodules [1]:
+ 
+-sh bin/getsnet
++    git submodule init
++    git submodule update
+ 
+ 4) Follow steps 2 and 3 from "More detailed instructions" for building, above.
+ 
+@@ -115,4 +115,7 @@ for details on how to join.
+ ----------
+ References
+ ----------
+-[1]: http://sourceforge.net/projects/libsnet
++[1]: Current submodules:
++
++    * libsnet, a networking library with TLS support
++	http://sourceforge.net/projects/libsnet
+diff --git a/aclocal.m4 b/aclocal.m4
+index 24b1b0f..0b7d456 100644
+--- ./aclocal.m4
++++ ./aclocal.m4
+@@ -105,16 +105,11 @@ AC_DEFUN([CHECK_UNIVERSAL_BINARIES],
+ 	    arches="-arch i386 -arch ppc"
+ 	    ;;
+ 
+-	  darwin9*)
++	  darwin9*|darwin10*|darwin11*)
+ 	    dep_target="-mmacosx-version-min=10.4"
+ 	    macosx_sdk="MacOSX10.5.sdk"
+ 	    arches="-arch i386 -arch x86_64 -arch ppc -arch ppc64"
+-	    ;;
+-
+-	  darwin10*)
+-	    dep_target="-mmacosx-version-min=10.4"
+-	    macosx_sdk="MacOSX10.6.sdk"
+-	    arches="-arch i386 -arch x86_64 -arch ppc"
++	    LDFLAGS="$LDFLAGS -L/Developer/SDKs/$macosx_sdk/usr/lib"
+ 	    ;;
+ 
+ 	  *)
+@@ -129,3 +124,20 @@ AC_DEFUN([CHECK_UNIVERSAL_BINARIES],
+     fi
+ ])
+ 
++AC_DEFUN([MACOSX_MUTE_DEPRECATION_WARNINGS],
++[
++    dnl Lion deprecates a system-provided OpenSSL. Build output
++    dnl is cluttered with useless deprecation warnings.
++
++    AS_IF([test x"$CC" = x"gcc"], [
++        case "${host_os}" in
++        darwin11*)
++            AC_MSG_NOTICE([muting deprecation warnings from compiler])
++            OPTOPTS="$OPTOPTS -Wno-deprecated-declarations"
++            ;;
++
++        *)
++            ;;
++        esac
++    ])
++])
+diff --git a/argcargv.c b/argcargv.c
+index 44111af..d78ca47 100644
+--- ./argcargv.c
++++ ./argcargv.c
+@@ -48,7 +48,9 @@ acav_parse( ACAV *acav, char *line, char **argv[] )
+ 
+     if ( acav == NULL ) {
+ 	if ( acavg == NULL ) {
+-	    acavg = acav_alloc();
++	    if (( acavg = acav_alloc()) == NULL ) {
++		return( -1 );
++	    }
+ 	}
+ 	acav = acavg;
+     }
+diff --git a/bin/getsnet b/bin/getsnet
+deleted file mode 100755
+index 1136f54..0000000
+--- ./bin/getsnet
++++ /dev/null
+@@ -1,16 +0,0 @@
+-#! /bin/sh
+-
+-# getsnet: download libsnet source code from SF.net
+-
+-proj="libsnet"
+-rev="1.0.1"
+-gitroot="git://${proj}.git.sourceforge.net/gitroot/${proj}/${proj}"
+-
+-[ -e "${proj}" ] && echo "${proj} already retrieved" && exit 1
+-[ ! -e "${proj}" ]							\
+-	&& git clone ${gitroot}						\
+-	&& (cd "${proj}"						\
+-	    && git checkout -b "${proj}-${rev}-branch" "${proj}-${rev}"	\
+-	    && autoconf)
+-
+-exit $?
+diff --git a/command.c b/command.c
+index 9cf6510..5dc0a54 100644
+--- ./command.c
++++ ./command.c
+@@ -477,38 +477,90 @@ f_retr( SNET *sn, int ac, char **av )
+ 
+ /* looks for special file info in transcripts */
+     char **
+-special_t( char *transcript, char *epath )
++special_t( char *sp_path, char *remote_path )
+ {
+-    FILE		*fs;
+-    int			ac, len;
+-    char		**av;
++    FILE		*fs = NULL;
++    int			i, ac, len, ln;
++    char		**av = NULL;
++    char		*paths[ 4 ] = { NULL };
++    char		*p;
++    char		sp_t[ MAXPATHLEN ];
+     static char		line[ MAXPATHLEN ];
+ 
+-    if (( fs = fopen( transcript, "r" )) == NULL ) {
+-	return( NULL );
+-    }
+-
+-    while ( fgets( line, MAXPATHLEN, fs ) != NULL ) {
+-	len = strlen( line );
+-	if (( line[ len - 1 ] ) != '\n' ) {
+-	    syslog( LOG_ERR, "special_t: %s: line too long", transcript );
+-	    break;
++    /*
++     * in order, we look for special file transcript lines in the
++     * following locations:
++     *
++     *      - A transcript in the same directory and with the same name
++     *	      as the special file, but with a ".T" extension.
++     *
++     *      - A transcript named "<remote_id>.T" in the same directory as
++     *        the client's special file directory root.
++     *
++     *      - /var/radmind/transcript/special.T
++     *
++     * if no matching transcript line is found, default metadata is
++     * returned to the client (type: f; mode: 0444; owner: 0; group: 0).
++     */
++    paths[ 0 ] = sp_path;
++    paths[ 1 ] = special_dir;
++    paths[ 2 ] = "transcript/special.T";
++    paths[ 3 ] = NULL;
++
++    for ( i = 0; paths[ i ] != NULL; i++ ) {
++	if (( p = strrchr( paths[ i ], '.' )) != NULL
++		&& strcmp( p, ".T" ) == 0 ) {
++	    if ( strlen( paths[ i ] ) >= MAXPATHLEN ) {
++		syslog( LOG_WARNING, "special_t: path \"%s\" too long",
++			paths[ i ] );
++		continue;
++	    }
++	    strcpy( sp_t, paths[ i ] );
++	} else if ( snprintf( sp_t, MAXPATHLEN, "%s.T",
++			      paths[ i ] ) >= MAXPATHLEN ) {
++	    syslog( LOG_WARNING, "special_t: path \"%s.T\" too long", sp_path );
++	    continue;
+ 	}
+ 
+-	if (( ac = argcargv( line, &av )) != 8 ) {
++	if (( fs = fopen( sp_t, "r" )) == NULL ) {
+ 	    continue;
+ 	}
+-	if (( *av[ 0 ] != 'f' ) && ( *av[ 0 ] != 'a' )) {
+-	    continue;
++
++	ln = 0;
++	while ( fgets( line, MAXPATHLEN, fs ) != NULL ) {
++	    ln++;
++	    len = strlen( line );
++	    if (( line[ len - 1 ] ) != '\n' ) {
++		syslog( LOG_ERR, "special_t: %s: line %d too long", sp_t, ln );
++		break;
++	    }
++
++	    /* only files and applefiles allowed */
++	    if ( strncmp( line, "f ", strlen( "f " )) != 0 &&
++			strncmp( line, "a ", strlen( "a " )) != 0 ) {
++		continue;
++	    }
++	    if (( ac = argcargv( line, &av )) != 8 ) {
++		syslog( LOG_WARNING, "special_t: %s: line %d: "
++			"bad transcript line", sp_t, ln );
++		continue;
++	    }
++
++	    if ( strcmp( av[ 1 ], remote_path ) == 0 ) { 
++		(void)fclose( fs );
++		return( av );
++	    }
+ 	}
+ 
+-	if ( strcmp( av[ 1 ], epath ) == 0 ) { 
+-	    (void)fclose( fs );
+-	    return( av );
++	if ( fclose( fs ) != 0 ) {
++	    syslog( LOG_WARNING, "special_t: fclose %s: %m", sp_t );
+ 	}
++	fs = NULL;
+     }
+-
+-    (void)fclose( fs );
++    if ( fs != NULL ) {
++	(void)fclose( fs );
++    }
++    
+     return( NULL );
+ }
+ 
+@@ -624,11 +676,11 @@ f_stat( SNET *sn, int ac, char *av[] )
+     switch ( key ) {
+     case K_COMMAND:
+ 	if ( ac == 2 ) {
+-	    snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
++	    snet_writef( sn, RADMIND_STAT_FMT,
+ 		"f", "command", DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
+ 		st.st_mtime, st.st_size, cksum_b64 );
+ 	} else {
+-	    snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
++	    snet_writef( sn, RADMIND_STAT_FMT,
+ 		"f", av[ 2 ], DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
+ 		st.st_mtime, st.st_size, cksum_b64 );
+ 	}
+@@ -636,61 +688,33 @@ f_stat( SNET *sn, int ac, char *av[] )
+         
+ 		    
+     case K_TRANSCRIPT:
+-	snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
++	snet_writef( sn, RADMIND_STAT_FMT,
+ 		"f", av[ 2 ], 
+ 		DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
+ 		st.st_mtime, st.st_size, cksum_b64 );
+ 	return( 0 );
+     
+     case K_SPECIAL:
+-	/*  status on a special file comes from 1 of three cases:
+-	 *  1. A transcript in the special file directory
+-	 *  2. A transcript in the Transcript dir with .T appended
+-	 *  3. No transcript is found, and constants are returned
+-	 */
+-
+-        /* look for transcript containing the information */
+-	if ( ( strlen( path ) + 2 ) > MAXPATHLEN ) {
+-	    syslog( LOG_WARNING, 
+-		"f_stat: transcript path longer than MAXPATHLEN" );
+-
+-	    /* return constants */
+-	    snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
+-		    "f", av[ 2 ], 
+-		    DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID,
+-		    st.st_mtime, st.st_size, cksum_b64 );
+-	    return( 0 );
+-	}
+-
+-	/* if allowable, check for transcript in the special file directory */
+-
+-	strcat( path, ".T" );
+-
+-	/* store value of av[ 2 ], because argcargv will be called
++	/*
++	 * store value of av[ 2 ], because argcargv will be called
+ 	 * from special_t(), and that will blow away the current values
+-	 * for av[ 2 ]
+-	 *
+-	 * Could just use new argvargc API... XXX  Notice how we never free
+-	 * env_file...
++	 * for av[ 2 ].
+ 	 */
+-
+ 	if (( enc_file = strdup( av[ 2 ] )) == NULL ) {
+ 	    syslog( LOG_ERR, "f_stat: strdup: %s %m", av[ 2 ] );
+ 	    return( -1 );
+ 	}
+ 
+ 	if (( av = special_t( path, enc_file )) == NULL ) {
+-	    if (( av = special_t( "transcript/special.T", enc_file ))
+-		    == NULL ) {
+-		snet_writef( sn, "%s %s %o %d %d %d %" PRIofft "d %s\r\n",
+-			"f", enc_file, 
+-			DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, 
+-			st.st_mtime, st.st_size, cksum_b64 );
+-		free( enc_file );
+-		return( 0 );
+-	    }
++	    /* no special transcript match found, return defaults. */
++	    snet_writef( sn, RADMIND_STAT_FMT,
++		    "f", enc_file, 
++		    DEFAULT_MODE, DEFAULT_UID, DEFAULT_GID, 
++		    st.st_mtime, st.st_size, cksum_b64 );
++	    free( enc_file );
++	    return( 0 );
+ 	}
+-	snet_writef( sn, "%s %s %s %s %s %d %" PRIofft "d %s\r\n",
++	snet_writef( sn, RADMIND_STAT_FMT,
+ 		av[ 0 ], enc_file,
+ 		av[ 2 ], av[ 3 ], av[ 4 ],
+ 		st.st_mtime, st.st_size, cksum_b64 );
+@@ -1261,8 +1285,7 @@ command_k( char *path_config, int depth )
+ 	    continue;
+ 	}
+ 	if ( strcmp( av[ 0 ], "@include" ) == 0 ) {
+-	    depth++;
+-	    if ( depth > RADMIND_MAX_INCLUDE_DEPTH ) {
++	    if ( depth >= RADMIND_MAX_INCLUDE_DEPTH ) {
+ 		syslog( LOG_ERR, "%s: line %d: include %s exceeds max depth",
+ 			path_config, linenum, av[ 1 ] );
+ 		goto command_k_done;
+@@ -1277,7 +1300,7 @@ command_k( char *path_config, int depth )
+ 		    continue;
+ 		}
+ 	    }
+-	    if ( command_k( av[ 1 ], depth ) != 0 ) {
++	    if ( command_k( av[ 1 ], depth + 1 ) != 0 ) {
+ 		continue;
+ 	    }
+ 
+@@ -1325,7 +1348,8 @@ command_k( char *path_config, int depth )
+ 
+     /* If we get here, the host that connected is not in the config
+        file. So screw him. */
+-    syslog( LOG_ERR, "host not in config file: %s", remote_host );
++    syslog( LOG_ERR, "host %s not in config file %s",
++		remote_host, path_config );
+ 
+ command_k_done:
+     snet_close( sn );
+diff --git a/command.h b/command.h
+index b0ea9f5..e0ee775 100644
+--- ./command.h
++++ ./command.h
+@@ -13,3 +13,5 @@ struct command {
+     char	*c_name;
+     int		(*c_func)( SNET *, int, char *[] );
+ };
++
++#define RADMIND_STAT_FMT "%s %s %o %d %d %" PRItimet "d %" PRIofft "d %s\r\n"
+diff --git a/configure.ac b/configure.ac
+index 43a243c..e724f32 100644
+--- ./configure.ac
++++ ./configure.ac
+@@ -44,25 +44,36 @@ AC_SYS_LARGEFILE
+ 
+ # Check sizes
+ AC_CHECK_SIZEOF(off_t)
++AC_CHECK_SIZEOF(time_t)
++
++# check early to make any required changes to environment for following tests.
++CHECK_UNIVERSAL_BINARIES
++
++# mute Mac OS X's helpful notices that using dylib OpenSSL
++MACOSX_MUTE_DEPRECATION_WARNINGS
+ 
+ # Checks for libraries.
+ AC_CHECK_LIB(c, inet_aton, libc_inet_aton=yes) 
+ if test x$libc_inet_aton != xyes; then 
+     AC_CHECK_LIB(resolv, inet_aton) 
+ fi 
+-AC_CHECK_LIB(c, lchown)
+-AC_CHECK_LIB(c, lchmod)
++if test x$host_vendor = xapply; then
++    AC_CHECK_LIB(c, lchown, [AC_DEFINE(HAVE_LCHOWN)], [])
++    AC_CHECK_LIB(c, lchmod, [AC_DEFINE(HAVE_LCHMOD)], [])
++fi
+ AC_CHECK_LIB(nsl, gethostbyaddr)
+ AC_CHECK_LIB([socket], [socket])
+ AC_CHECK_LIB([ssl], [SSL_accept], , [CHECK_SSL])
+ AC_CHECK_HEADER([openssl/ssl.h], [], [AC_MSG_ERROR([header file <openssl/ssl.h>
+ is required for this software.  You may be running RedHat 9.  If so, see the FAQ or the README for further instructions.])])
+ AC_CHECK_LIB([crypto], [SSLeay_version], , [CHECK_SSL])
+-AC_CHECK_FUNC([X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], [])
++AC_CHECK_LIB([crypto], [X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], [])
+ 
+ # PAM
+-AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=yes], [Pluggable Authentication Module support (default: yes)]), [], with_pam=yes)
++AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=PATH], [Pluggable Authentication Module support (default: /usr)]), [], with_pam=/usr)
+ if test x_"$with_pam" != x_no; then
++    CPPFLAGS="${CPPFLAGS} -I$with_pam/include"
++    LDFLAGS="${LDFLAGS} -L$with_pam/lib"
+     AC_CHECK_LIB([pam], [pam_start],
+ 	[
+ 	AC_CHECK_HEADERS(pam/pam_appl.h, , [AC_CHECK_HEADERS(security/pam_appl.h)])
+@@ -75,7 +86,6 @@ AC_CHECK_HEADER([dns_sd.h], [AC_DEFINE(HAVE_DNSSD)], [], [])
+ AC_CHECK_LIB(dns_sd, DNSServiceRegister)
+ 
+ CHECK_ZLIB
+-CHECK_UNIVERSAL_BINARIES
+ 
+ # HPUX lacks wait4 and strtoll
+ AC_CHECK_FUNCS(wait4 strtoll)
+diff --git a/contrib/specialist b/contrib/specialist
+new file mode 100755
+index 0000000..ee796ac
+--- /dev/null
++++ ./contrib/specialist
+@@ -0,0 +1,79 @@
++#! /bin/sh
++
++# specialist: assist creation of special files.
++
++PATH=/bin:/usr/bin:/usr/local/bin; export PATH
++
++SCRIPT=`basename "$0"`
++INPUT_FORMAT=${INPUT_FORMAT:=path}
++
++usage() {
++    echo "usage: ${SCRIPT} [ -T ]" 1>&2
++    exit 1
++}
++
++die() {
++    msg=$*
++
++    echo "${msg}" 1>&2
++    exit 2
++}
++
++# create a special transcript line for the given path.
++specialize() {
++    local path="$1"
++
++    [ -n "${path}" -a -f "${path}" ] || die "Invalid path: ${path}"
++
++    fsdiff -1 -c sha1 "${path}"
++    return $?
++}
++
++specialize_transcript() {
++    local path=""
++    status=0
++
++    while read type path remainder; do
++	if [ x"${type}" != x"f" ]; then
++	    continue
++	fi
++
++	specialize "${path}"
++    done
++}
++
++specialize_paths() {
++    local path=""
++    status=0
++
++    while read path; do
++	specialize "${path}"
++	if [ $? -ne 0 ]; then
++	    status=1
++	fi
++    done
++
++    return "${status}"
++}
++
++while getopts T opt; do
++    case $opt in
++    T)
++	INPUT_FORMAT="transcript"
++	;;
++
++    *)
++	usage
++	;;
++	
++    esac
++done
++shift $((OPTIND - 1))
++
++if [ x"${INPUT_FORMAT}" = x"transcript" ]; then
++    specialize_transcript
++else
++    specialize_paths
++fi
++
++exit $?
+diff --git a/fsdiff.c b/fsdiff.c
+index 61fbb03..57d3ff0 100644
+--- ./fsdiff.c
++++ ./fsdiff.c
+@@ -249,6 +249,144 @@ fs_walk( char *path, struct stat *st, char *type, struct applefileinfo *afinfo,
+     return;
+ }
+ 
++    static char *
++canonicalized_path( char *path )
++{
++    int			len;
++    static char		cpath[ MAXPATHLEN ];
++
++    if ( path == NULL ) {
++	return( NULL );
++    }
++
++    len = strlen( path );
++    if ( len >= sizeof( cpath )) {
++	fprintf( stderr, "fsdiff: path too long: %s\n", path );
++	exit( 2 );
++    }
++    strcpy( cpath, path );
++
++    /* Clip trailing '/' */
++    if (( len > 1 ) && ( cpath[ len - 1 ] == '/' )) {
++	cpath[ len - 1 ] = '\0';
++	len--;
++    }
++
++    /*
++     * If prefix doesn't contain a directory, canonicalize it by prepending a
++     * "./".  This allow paths to be dynamically converted between relative and
++     * absolute paths without breaking sort order.
++     */
++    switch( cpath[ 0 ] ) {
++    case '/':
++        break;
++
++    case '.':
++	/* Don't rewrite '.' or paths starting with './' */
++	if ( len == 1 || cpath[ 1 ] == '/' ) {
++	    break;
++	}
++
++    default:
++	if ( len + 2 >= sizeof( cpath )) {
++	    fprintf( stderr, "fsdiff: path too long: ./%s\n", cpath );
++	    exit( 2 );
++	}
++	memmove( cpath + 2, cpath, len );
++	cpath[ 0 ] = '.'; cpath[ 1 ] = '/';
++
++        break;
++    }
++
++    /*
++     * Determine if called with relative or absolute pathing.  Path is relative
++     * if it's just '.' or starts with './'.  File names that start with a '.'
++     * are absolute.
++     */
++    if ( cpath[ 0 ] == '.' ) {
++	if ( len == 1 ) {
++	    tran_format = T_RELATIVE;
++	} else if ( cpath[ 1 ] == '/' ) {
++	    tran_format = T_RELATIVE;
++	} else {
++	    tran_format = T_ABSOLUTE;
++	}
++    } else {
++	tran_format = T_ABSOLUTE;
++    }
++
++    return( cpath );
++}
++
++    static void
++fsdiff( char *path, char *kfile, int start, int finish, int pdel ) 
++{
++    struct applefileinfo	afinfo;
++    struct stat			st;
++    char			type;
++    char			lpath[ MAXPATHLEN ];
++    int				len;
++
++    if (( dotfd = open( ".", O_RDONLY, 0 )) < 0 ) {
++	perror( "OOPS!" );
++	exit( 2 );
++    }
++
++    if ( skip && strcmp( path, "-" ) == 0 ) {
++	/* leave excludes in place */
++	skip = skip & ~T_SKIP_EXCLUDES;
++
++	path_prefix = "/";
++	transcript_init( kfile, K_CLIENT );
++
++	/* run -1 against every line we get from stdin */
++	while ( fgets( lpath, sizeof( lpath ), stdin ) != NULL ) {
++	    len = strlen( lpath );
++	    if ( lpath[ len - 1 ] != '\n' ) {
++		fprintf( stderr, "fsdiff: fgets: line too long\n" );
++		exit( 2 );
++	    }
++	    lpath[ len - 1 ] = '\0';
++	    path = canonicalized_path( lpath );
++
++	    if ( radstat( path, &st, &type, &afinfo ) != 0 ) {
++		if ( errno != ENOENT ) {
++		    perror( lpath );
++		    exit( 2 );
++		}
++
++		fprintf( stderr, "Warning: %s: %s\n", path, strerror( errno ));
++		continue;
++	    }
++	    (void)transcript( path, &st, &type, &afinfo, pdel );
++	}
++	if ( ferror( stdin )) {
++	    perror( "fgets" );
++	    exit( 2 );
++	}
++    } else {
++	path_prefix = canonicalized_path( path );
++
++	/* initialize the transcripts */
++	transcript_init( kfile, K_CLIENT );
++
++	if ( radstat( path_prefix, &st, &type, &afinfo ) != 0 ) {
++	    perror( path_prefix );
++	    exit( 2 );
++	}
++
++	fs_walk( path_prefix, &st, &type, &afinfo, start, finish, pdel );
++    }
++
++    if ( finish > 0 ) {
++	printf( "%%%d\n", ( int )finish );
++    }
++
++    /* free the transcripts */
++    transcript_free( );
++    hardlink_free( );
++}
++
+     int
+ main( int argc, char **argv ) 
+ {
+@@ -258,9 +396,6 @@ main( int argc, char **argv )
+     int 		c, len, edit_path_change = 0;
+     int 		errflag = 0, use_outfile = 0;
+     int			finish = 0;
+-    struct stat		st;
+-    char		type, buf[ MAXPATHLEN ];
+-    struct applefileinfo	afinfo;
+ 
+     edit_path = CREATABLE;
+     cksum = 0;
+@@ -300,7 +435,7 @@ main( int argc, char **argv )
+ 	    break;
+ 
+ 	case '1':
+-	    skip = 1;
++	    skip = T_SKIP_ALL;
+ 	case 'C':
+ 	    edit_path_change++;
+ 	    edit_path = CREATABLE;
+@@ -347,82 +482,13 @@ main( int argc, char **argv )
+     }
+ 
+     if ( errflag || ( argc - optind != 1 )) {
+-	fprintf( stderr, "usage: %s { -C | -A | -1 } [ -IVW ] ", argv[ 0 ] );
++	fprintf( stderr, "usage: %s { -C | -A | -1 } " "[ -IVW ] ", argv[ 0 ] );
+ 	fprintf( stderr, "[ -K command ] " );
+ 	fprintf( stderr, "[ -c checksum ] [ -o file [ -%% ] ] path\n" );
+ 	exit ( 2 );
+     }
+ 
+-    path_prefix = argv[ optind ];
+-    len = strlen( path_prefix );
+-
+-    /* Clip trailing '/' */
+-    if (( len > 1 ) && ( path_prefix[ len - 1 ] == '/' )) {
+-	path_prefix[ len - 1 ] = '\0';
+-	len--;
+-    }
+-
+-    /* If path_prefix doesn't contain a directory, canonicalize it by
+-     * prepending a "./".  This allow paths to be dynamically converted between
+-     * relative and absolute paths without breaking sort order.
+-     */
+-    switch( path_prefix[ 0 ] ) {
+-    case '/':
+-        break;
+-
+-    case '.':
+-	/* Don't rewrite '.' or paths starting with './' */
+-	if (( len == 1 ) || (  path_prefix[ 1 ] == '/' )) {
+-	    break;
+-	}
+-    default:
+-        if ( snprintf( buf, sizeof( buf ), "./%s",
+-                path_prefix ) >= MAXPATHLEN ) {
+-            fprintf( stderr, "path too long\n" );
+-            exit( 2 );
+-        }
+-	path_prefix = buf;
+-        break;
+-    }
+-
+-    /* Determine if called with relative or absolute pathing.  Path is relative
+-     * if it's just '.' or starts with './'.  File names that start with a '.'
+-     * are absolute.
+-     */
+-    if ( path_prefix[ 0 ] == '.' ) {
+-	if ( len == 1 ) {
+-	    tran_format = T_RELATIVE;
+-	} else if ( path_prefix[ 1 ] == '/' ) {
+-	    tran_format = T_RELATIVE;
+-	} else {
+-	    tran_format = T_ABSOLUTE;
+-	}
+-    } else {
+-	tran_format = T_ABSOLUTE;
+-    }
+-
+-    if ( radstat( path_prefix, &st, &type, &afinfo ) != 0 ) {
+-	perror( path_prefix );
+-	exit( 2 );
+-    }
+-
+-    if (( dotfd = open( ".", O_RDONLY, 0 )) < 0 ) {
+-	perror( "OOPS!" );
+-	exit( 2 );
+-    }
+-
+-    /* initialize the transcripts */
+-    transcript_init( kfile, K_CLIENT );
+-
+-    fs_walk( path_prefix, &st, &type, &afinfo, 0, finish, 0 );
+-
+-    if ( finish > 0 ) {
+-	printf( "%%%d\n", ( int )finish );
+-    }
+-
+-    /* free the transcripts */
+-    transcript_free( );
+-    hardlink_free( );
++    fsdiff( argv[ optind ], kfile, 0, finish, 0 );
+ 
+     /* close the output file */     
+     fclose( outtran );
+diff --git a/ktcheck.c b/ktcheck.c
+index 567a555..9d1f41d 100644
+--- ./ktcheck.c
++++ ./ktcheck.c
+@@ -459,7 +459,7 @@ check( SNET *sn, char *type, char *file )
+ 	perror( "Incorrect number of arguments\n" );
+ 	return( 2 );
+     }
+-    times.modtime = atoi( targv[ 5 ] );
++    times.modtime = strtotimet( targv[ 5 ], NULL, 10 );
+     times.actime = time( NULL );
+ 
+     if (( stat( path, &st )) != 0 ) {
+@@ -506,7 +506,7 @@ check( SNET *sn, char *type, char *file )
+ 		needupdate = 1;
+ 	    }
+ 	} else {
+-	    if ( atoi( targv[ 5 ] ) != (int)st.st_mtime )  {
++	    if ( strtotimet( targv[ 5 ], NULL, 10 ) != st.st_mtime )  {
+ 		needupdate = 1;
+ 	    }
+ 	}
+diff --git a/lapply.c b/lapply.c
+index c13ad9e..3749617 100644
+--- ./lapply.c
++++ ./lapply.c
+@@ -651,27 +651,37 @@ dirchecklist:
+ filechecklist:
+ 		if ( head == NULL ) {
+ 		    if ( unlink( path ) != 0 ) {
+-			perror( path );
+-			goto error2;
+-		    }
+-		    if ( !quiet && !showprogress ) {
+-			printf( "%s: deleted\n", path );
+-		    }
+-		    if ( showprogress ) {
+-			progressupdate( PROGRESSUNIT, path );
+-		    }
+-		} else {
+-		    if ( ischildcase( path, head->path, case_sensitive )) {
+-			if ( unlink( path ) != 0 ) {
++			if ( !force || errno != ENOENT ) {
+ 			    perror( path );
+ 			    goto error2;
+ 			}
++			fprintf( stderr, "Warning: failed to remove %s: %s\n",
++				path, strerror( errno ));
++		    } else {
+ 			if ( !quiet && !showprogress ) {
+ 			    printf( "%s: deleted\n", path );
+ 			}
+ 			if ( showprogress ) {
+ 			    progressupdate( PROGRESSUNIT, path );
+ 			}
++		    }
++		} else {
++		    if ( ischildcase( path, head->path, case_sensitive )) {
++			if ( unlink( path ) != 0 ) {
++			    if ( !force || errno != ENOENT ) {
++				perror( path );
++				goto error2;
++			    }
++			    fprintf( stderr, "Warning: failed to remove %s: "
++				    "%s\n", path, strerror( errno ));
++			} else {
++			    if ( !quiet && !showprogress ) {
++				printf( "%s: deleted\n", path );
++			    }
++			    if ( showprogress ) {
++				progressupdate( PROGRESSUNIT, path );
++			    }
++			}
+ 		    } else {
+ 			/* remove head */
+ 			if ( rmdir( head->path ) != 0 ) {
+diff --git a/largefile.h b/largefile.h
+index 4a11d3b..3a09ce9 100644
+--- ./largefile.h
++++ ./largefile.h
+@@ -18,3 +18,15 @@
+ #define strtoofft(x,y,z)	(strtol((x),(y),(z)))
+ #define PRIofft			"l"
+ #endif
++
++#if SIZEOF_TIME_T == 8
++    #ifdef HAVE_STRTOLL
++    #define strtotimet(x,y,z)	(strtoll((x),(y),(z)))
++    #else /* !HAVE_STRTOLL */
++    #define strtotimet(x,y,z)	(strtol((x),(y),(z)))
++    #endif /* HAVE_STRTOLL */
++    #define PRItimet		"ll"
++#else /* SIZEOF_TIME_T != 8 */
++    #define strtotimet(x,y,z)	(strtol((x),(y),(z)))
++    #define PRItimet		"l"
++#endif /* SIZEOF_TIME_T */
+diff --git a/lcksum.c b/lcksum.c
+index 40d3c1e..cc09f8c 100644
+--- ./lcksum.c
++++ ./lcksum.c
+@@ -434,7 +434,7 @@ do_lcksum( char *tpath )
+ 		/* Check to see if checksum is listed in transcript */
+ 		if ( strcmp( targv[ 7 ], "-" ) != 0) {
+ 		    /* use mtime from server */
+-		    fprintf( ufs, "%s %-37s %4s %5s %5s %9ld "
++		    fprintf( ufs, "%s %-37s %4s %5s %5s %9" PRItimet "d "
+ 			    "%7" PRIofft "d %s\n",
+ 			targv[ 0 ], targv[ 1 ], targv[ 2 ], targv[ 3 ],
+ 			targv[ 4 ], st.st_mtime, st.st_size, lcksum );
+@@ -457,6 +457,12 @@ done:
+ 	}
+ 	free( line );
+     }
++    if ( fclose( f ) != 0 ) {
++	fprintf( stderr, "%s: fclose failed: %s\n", path, strerror( errno ));
++	cleanup( updatetran, upath );
++	exit( 2 );
++    }
++
+     if ( showprogress ) {
+ 	progressupdate( bytes, "" );
+     }
+@@ -496,6 +502,10 @@ done:
+ badline:
+     exitval = 1;
+ 
++    if ( fclose( f ) != 0 ) {
++	fprintf( stderr, "%s: fclose failed: %s\n", path, strerror( errno ));
++    }
++
+     if ( checkall ) {
+ 	goto done;
+     } else {
+diff --git a/man/lcreate.1 b/man/lcreate.1
+index 64bdcc2..658c1fc 100644
+--- ./man/lcreate.1
++++ ./man/lcreate.1
+@@ -45,12 +45,6 @@ will store the file on the server and give a warning.
+ .sp
+ If the -n option is given, no files or transcripts are uploaded.  Instead,
+ .B lcreate
+-verifies that all files exist in the filesystem and have
+-the same size as listed in the transcript.  If used with the -c option,
+-checksums are also verified.
+-.sp
+-If the -n option is given, no files or transcripts are uploaded.  Instead,
+-.B lcreate
+ uses 
+ .BR access (2)
+ to verify that all files in the transcript exist in the
+diff --git a/man/rash.1 b/man/rash.1
+index 92c77d3..52fc6f0 100644
+--- ./man/rash.1
++++ ./man/rash.1
+@@ -11,6 +11,10 @@
+ |
+ .B -q
+ ] [
++.BR \-C\  "generate"
++|
++.BI \-C\  checksum
++] [
+ .B \-D
+ .I workingdir
+ ] [
+@@ -120,6 +124,24 @@ to use percentage done progress output.
+ .B \-c
+ use sha1 checksums.
+ .TP 19
++.BR \-C\  "generate"
++Print a sha1 checksum of the difference transcript of applied changes. For use with
++.IR auto ,
++.IR force
++or
++.IR update .
++.TP 19
++.BI \-C\  checksum
++In
++.I auto
++mode, exit with an error if the checksum of the difference transcript to be applied does not match
++.IR checksum .
++In
++.I update
++or
++.I force
++mode, warn if the two do not match.
++.TP 19
+ .BI \-D\  workingdir
+ change to
+ .I workingdir
+diff --git a/mkdirs.c b/mkdirs.c
+index 3839432..65ddeba 100644
+--- ./mkdirs.c
++++ ./mkdirs.c
+@@ -37,7 +37,9 @@ mkdirs( char *path )
+ 	if ( mkdir( path, 0777 ) == 0 ) {
+ 	    break;
+ 	}
+-	if ( errno != ENOENT ) {
++	if ( errno == EEXIST ) {
++	    break;
++	} else if ( errno != ENOENT ) {
+ 	    return( -1 );
+ 	}
+ 	q = p;
+diff --git a/ra.sh b/ra.sh
+index 8ee8dd4..4152d27 100755
+--- ./ra.sh
++++ ./ra.sh
+@@ -91,7 +91,7 @@ checkedout() {
+ }
+ 
+ usage() {
+-    $ECHO "Usage:	$0 [ -ctV ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2
++    $ECHO "Usage:	$0 [ -cIltV ] [ -% | -q ] [ -C \"generate\" | -C <checksum> ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2
+     exit 1
+ }
+ 
+@@ -128,6 +128,38 @@ dopostapply() {
+     fi
+ }
+ 
++cksum_generate() {
++    if [ -n "$FSDIFF_CHECKSUM" ]; then
++	FTMP_CHECKSUM=`openssl sha1 ${FTMP} | awk '{ print $2 }'`
++    fi
++}
++
++cksum_compare() {
++    if [ -n "$FSDIFF_CHECKSUM" -a \
++	    "$FSDIFF_CHECKSUM" != "generate" -a \
++	    "$FSDIFF_CHECKSUM" != "$FTMP_CHECKSUM" ]; then
++	return 1
++    fi
++
++    return 0
++}
++
++cksum_print() {
++    if [ -n "$FSDIFF_CHECKSUM" ]; then
++	$ECHO "Difference transcript checksum: $FTMP_CHECKSUM"
++    fi
++}
++
++cksum_mismatch() {
++    if [ -n "$FSDIFF_CHECKSUM" ]; then
++	$ECHO
++	$ECHO "**** Difference transcript checksum mismatch!"
++	$ECHO "****	Expected: $FSDIFF_CHECKSUM"
++	$ECHO "****	Actual:   $FTMP_CHECKSUM"
++	#ECHO
++    fi
++}
++
+ update() {
+     opt="$1"
+     kopt=
+@@ -211,6 +243,11 @@ update() {
+     fi
+     if [ x"${opt}" = x"interactive" ]; then
+ 	while [ 1 ]; do
++	    cksum_generate
++	    if ! cksum_compare; then
++		cksum_mismatch
++	    fi
++
+ 	    if [ x"${can_edit}" = x"yes" ]; then
+ 		$ECHO -n "(e)dit difference transcript, "
+ 	    fi
+@@ -248,7 +285,8 @@ update() {
+ 		
+     lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP}
+     case "$?" in
+-    0)	;;
++    0)	cksum_print
++	;;
+ 
+     *)  if [ x"$opt" = x"hook" ]; then
+ 	    $ECHO -n "Applying changes failed, trying again "
+@@ -284,7 +322,7 @@ if [ -f "${DEFAULTS}" ]; then
+     . "${DEFAULTS}"
+ fi
+ 
+-while getopts %cD:h:Ilp:qr:tU:Vw: opt; do
++while getopts %C:cD:h:Ilp:qr:tU:Vw: opt; do
+     case $opt in
+     %)  PROGRESS="-%"
+ 	FPROGRESS="-%"
+@@ -293,6 +331,13 @@ while getopts %cD:h:Ilp:qr:tU:Vw: opt; do
+     q)  PROGRESS="-q"
+ 	;;
+ 
++    C)	FSDIFF_CHECKSUM="$OPTARG"
++	if ! type openssl >/dev/null 2>&1; then
++	    $ECHO "-C requires openssl, but no openssl found in PATH $PATH"
++	    cleanup_and_exit
++	fi
++	;;
++
+     c)	CHECKSUM="-csha1"
+ 	;;
+ 
+@@ -524,6 +569,14 @@ auto)
+ 		cleanup
+ 		exit 1
+ 	    fi
++
++	    cksum_generate
++	    if ! cksum_compare; then
++		$ECHO "Auto failure: `hostname`: difference cksum mismatch" 
++		cksum_mismatch
++		cleanup_and_exit
++	    fi
++
+ 	    dopreapply ${FTMP}
+ 	    if [ -s ${FTMP} ]; then
+ 		lapply ${NETOPTS} ${CASE} ${PROGRESS} \
+@@ -532,6 +585,7 @@ auto)
+ 		0)
+ 		    $ECHO Auto update: `hostname`
+ 		    cat ${FTMP}
++		    cksum_print
+ 		    dopostapply ${FTMP}
+ 		    cleanup
+ 		    break
+@@ -588,14 +642,17 @@ force)
+ 	exit 0
+     fi
+     
++    cksum_generate
++    cksum_compare || cksum_mismatch
+     dopreapply ${FTMP}
+     lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP}
+     case "$?" in
+-    0)	;;
++    0)	cksum_print
++	;;
+ 
+     *)	cleanup
+-	    exit $?
+-	    ;;
++	exit $?
++	;;
+     esac
+     dopostapply ${FTMP}
+     
+diff --git a/t2pkg.c b/t2pkg.c
+index ad43135..a75e8de 100644
+--- ./t2pkg.c
++++ ./t2pkg.c
+@@ -38,6 +38,7 @@ extern int	showprogress;
+ extern off_t	lsize;
+ extern char	*version;
+ 
++int		tran_format = -1;
+ int		cksum = 0;
+ int		force = 0;
+ int		case_sensitive = 1;
+@@ -718,31 +719,23 @@ main( int ac, char *av[] )
+ 	}
+ 
+ 	/* create the destination path */
+-	if ( snprintf( tmp, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name )
++	if ( snprintf( dst, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name )
+ 		>= MAXPATHLEN ) {
+ 	    fprintf( stderr, "%s/%s: path too long\n", dstdir,
+ 			t->t_pinfo.pi_name );
+ 	    exit( 2 );
+ 	}
+-	if ( mkdirs( tmp ) < 0 ) {
+-	    fprintf( stderr, "mkdirs %s: %s\n", tmp, strerror( errno ));
+-	}
+-	if ( realpath( tmp, dst ) == NULL ) {
+-	    fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno ));
+-	    exit( 2 );
++	if ( mkdirs( dst ) < 0 ) {
++	    fprintf( stderr, "mkdirs %s: %s\n", dst, strerror( errno ));
+ 	}
+ 
+ 	/* and the source path */
+-	if ( snprintf( tmp, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name )
++	if ( snprintf( src, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name )
+ 		>= MAXPATHLEN ) {
+ 	    fprintf( stderr, "%s/%s: path too long\n", dstdir,
+ 			t->t_pinfo.pi_name );
+ 	    exit( 2 );
+ 	}
+-	if ( realpath( tmp, src ) == NULL ) {
+-	    fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno ));
+-	    exit( 2 );
+-	}
+ 
+ 	if ( local_update( t, dst, src, where ) != 0 ) {
+ 	    /* XXX is this really a good idea? */
+diff --git a/transcript.c b/transcript.c
+index cad8d50..94e21ca 100644
+--- ./transcript.c
++++ ./transcript.c
+@@ -45,7 +45,7 @@ struct list			*exclude_list;
+ 
+ char				*path_prefix = NULL;
+ int				edit_path;
+-int				skip;
++int				skip = 0;
+ int				cksum;
+ int				fs_minus;
+ int				exclude_warnings = 0;
+@@ -271,7 +271,7 @@ transcript_parse( struct transcript *tran )
+ 	tran->t_pinfo.pi_stat.st_mode = strtol( argv[ 2 ], NULL, 8 );
+ 	tran->t_pinfo.pi_stat.st_uid = atoi( argv[ 3 ] );
+ 	tran->t_pinfo.pi_stat.st_gid = atoi( argv[ 4 ] );
+-	tran->t_pinfo.pi_stat.st_mtime = atoi( argv[ 5 ] );
++	tran->t_pinfo.pi_stat.st_mtime = strtotimet( argv[ 5 ], NULL, 10 );
+ 	tran->t_pinfo.pi_stat.st_size = strtoofft( argv[ 6 ], NULL, 10 );
+ 	if ( tran->t_type != T_NEGATIVE ) {
+ 	    if (( cksum ) && ( strcmp( "-", argv [ 7 ] ) == 0  )) {
+@@ -436,12 +436,13 @@ t_print( struct pathinfo *fs, struct transcript *tran, int flag )
+ 	 * but the corresponding transcript is negative, hence, retain
+ 	 * the file system's mtime.  Woof!
+ 	 */
+-	fprintf( outtran, "%c %-37s\t%.4lo %5d %5d %9d %7" PRIofft "d %s\n",
++	fprintf( outtran, "%c %-37s\t%.4lo %5d %5d %9" PRItimet "d "
++			  "%7" PRIofft "d %s\n",
+ 		cur->pi_type, epath,
+ 		(unsigned long)( T_MODE & cur->pi_stat.st_mode ), 
+ 		(int)cur->pi_stat.st_uid, (int)cur->pi_stat.st_gid,
+ 		( flag == PR_STATUS_NEG ) ?
+-			(int)fs->pi_stat.st_mtime : (int)cur->pi_stat.st_mtime,
++			fs->pi_stat.st_mtime : cur->pi_stat.st_mtime,
+ 		cur->pi_stat.st_size, cur->pi_cksum_b64 );
+ 	break;
+ 
+@@ -723,7 +724,7 @@ transcript_select( void )
+ 	    if ( begin_tran->t_type != T_SPECIAL &&
+ 		    t_exclude( begin_tran->t_pinfo.pi_name )) {
+ 		if ( exclude_warnings ) {
+-		    fprintf( stderr, "Warning: excluding %s\n",
++		    printf( "#! Warning: excluding %s\n",
+ 				begin_tran->t_pinfo.pi_name );
+ 		}
+ 		transcript_parse( begin_tran );
+@@ -769,7 +770,7 @@ transcript( char *path, struct stat *st, char *type,
+ 	    if ( list_size( special_list ) <= 0
+ 		    || list_check( special_list, path ) == 0 ) {
+ 		if ( exclude_warnings ) {
+-		    fprintf( stderr, "Warning: excluding %s\n", path );
++		    printf( "#! Warning: excluding %s\n", path );
+ 		}
+ 
+ 		/* move the transcripts ahead */
+@@ -949,7 +950,7 @@ transcript_init( char *kfile, int location )
+      */
+     t_new( T_NULL, NULL, NULL, NULL );
+ 
+-    if ( skip ) {
++    if ( skip == T_SKIP_ALL ) {
+ 	return;
+     }
+ 
+@@ -985,15 +986,17 @@ transcript_init( char *kfile, int location )
+ 	exit( 2 );
+     }
+ 
+-    if (( list_size( special_list ) > 0 ) && ( location == K_CLIENT )) {
+-	/* open the special transcript if there were any special files */
+-	if ( strlen( kdir ) + strlen( special ) + 2 > MAXPATHLEN ) {
+-	    fprintf( stderr, 
+-		    "special path too long: %s%s\n", kdir, special );
+-	    exit( 2 );
++    if ( !( skip & T_SKIP_SPECIAL )) {
++	if (( list_size( special_list ) > 0 ) && ( location == K_CLIENT )) {
++	    /* open the special transcript if there were any special files */
++	    if ( strlen( kdir ) + strlen( special ) + 2 > MAXPATHLEN ) {
++		fprintf( stderr, 
++			"special path too long: %s%s\n", kdir, special );
++		exit( 2 );
++	    }
++	    sprintf( fullpath, "%s%s", kdir, special );
++	    t_new( T_SPECIAL, fullpath, special, "special" );
+ 	}
+-	sprintf( fullpath, "%s%s", kdir, special );
+-	t_new( T_SPECIAL, fullpath, special, "special" );
+     }
+ 
+     if ( tran_head->t_type == T_NULL  && edit_path == APPLICABLE ) {
+@@ -1108,6 +1111,10 @@ read_kfile( char *kfile, int location )
+ 	    break;
+ 
+ 	case 'n':				/* negative */
++	    if ( skip & T_SKIP_NEGATIVE ) {
++		break;
++	    }
++
+ 	    if ( minus ) { 
+ 		t_remove( T_NEGATIVE, av[ 1 ] );
+ 	    } else {
+@@ -1116,6 +1123,10 @@ read_kfile( char *kfile, int location )
+ 	    break;
+ 
+ 	case 'p':				/* positive */
++	    if ( skip & T_SKIP_POSITIVE ) {
++		break;
++	    }
++
+ 	    if ( minus ) {
+ 		t_remove( T_POSITIVE, av[ 1 ] );
+ 	    } else {
+@@ -1124,6 +1135,10 @@ read_kfile( char *kfile, int location )
+ 	    break;
+ 
+ 	case 'x':				/* exclude */
++	    if ( skip & T_SKIP_EXCLUDES ) {
++		break;
++	    }
++
+ 	    if (( d_pattern = decode( av[ 1 ] )) == NULL ) {
+ 		fprintf( stderr, "%s: line %d: decode buffer too small\n",
+ 		    kfile, linenum );
+@@ -1149,6 +1164,10 @@ read_kfile( char *kfile, int location )
+ 	    break;
+ 
+ 	case 's':				/* special */
++	    if ( skip & T_SKIP_SPECIAL ) {
++		break;
++	    }
++
+ 	    path = av[ 1 ];
+ 
+ 	    /* Convert path to match transcript type */
+diff --git a/transcript.h b/transcript.h
+index 29ae3cf..f4453ca 100644
+--- ./transcript.h
++++ ./transcript.h
+@@ -39,6 +39,14 @@ extern int		fs_minus;
+ extern FILE		*outtran;
+ extern char		*path_prefix;
+ 
++
++#define T_SKIP_POSITIVE		(1 << 1)
++#define T_SKIP_NEGATIVE		(1 << 2)
++#define T_SKIP_SPECIAL		(1 << 3)
++#define T_SKIP_EXCLUDES		(1 << 4)
++#define	T_SKIP_ALL		(T_SKIP_POSITIVE | T_SKIP_NEGATIVE | \
++				 T_SKIP_SPECIAL | T_SKIP_EXCLUDES)
++
+ struct pathinfo {
+     char			pi_type;
+     int				pi_minus;
+diff --git a/update.c b/update.c
+index fa4227d..47911cc 100644
+--- ./update.c
++++ ./update.c
+@@ -26,6 +26,7 @@
+ #include "update.h"
+ #include "code.h"
+ #include "radstat.h"
++#include "largefile.h"
+ #include "transcript.h"
+ #include "progress.h"
+ #include "mkdirs.h"
+@@ -73,7 +74,7 @@ update( char *path, char *displaypath, int present, int newfile,
+ 
+ 	mode = strtol( targv[ 2 ], (char **)NULL, 8 );
+ 
+-	times.modtime = atoi( targv[ 5 ] );
++	times.modtime = strtotimet( targv[ 5 ], NULL, 10 );
+ 	if ( times.modtime != st->st_mtime ) {
+ 	    times.actime = st->st_atime;
+ 	    if ( utime( path, &times ) != 0 ) {
diff -ruN ./files/patch-Makefile.in ./files/patch-Makefile.in
--- ./files/patch-Makefile.in	2014-05-22 14:34:26.000000000 -0400
+++ ./files/patch-Makefile.in	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
---- ./Makefile.in.orig	2010-12-12 22:43:49.000000000 -0500
-+++ ./Makefile.in	2012-03-20 14:37:54.000000000 -0400
-@@ -204,37 +204,37 @@
- radmind : libsnet/libsnet.la ${RADMIND_OBJ} Makefile
- 	${CC} ${CFLAGS} -o radmind ${RADMIND_OBJ} ${LDFLAGS}
- 
--fsdiff : ${FSDIFF_OBJ}
-+fsdiff : libsnet/libsnet.la ${FSDIFF_OBJ}
- 	${CC} ${CFLAGS} -o fsdiff ${FSDIFF_OBJ} ${LDFLAGS}
- 
--ktcheck: ${KTCHECK_OBJ}
-+ktcheck: libsnet/libsnet.la ${KTCHECK_OBJ}
- 	${CC} ${CFLAGS} -o ktcheck ${KTCHECK_OBJ} ${LDFLAGS}
- 
--lapply: ${LAPPLY_OBJ}
-+lapply: libsnet/libsnet.la ${LAPPLY_OBJ}
- 	${CC} ${CFLAGS} -o lapply ${LAPPLY_OBJ} ${LDFLAGS}
- 
--lcksum: ${LCKSUM_OBJ}
-+lcksum: libsnet/libsnet.la ${LCKSUM_OBJ}
- 	${CC} ${CFLAGS} -o lcksum ${LCKSUM_OBJ} ${LDFLAGS}
- 
--lcreate: ${LCREATE_OBJ}
-+lcreate: libsnet/libsnet.la ${LCREATE_OBJ}
- 	${CC} ${CFLAGS} -o lcreate ${LCREATE_OBJ} ${LDFLAGS}
- 
--lmerge: ${LMERGE_OBJ}
-+lmerge: libsnet/libsnet.la ${LMERGE_OBJ}
- 	${CC} ${CFLAGS} -o lmerge ${LMERGE_OBJ} ${LDFLAGS}
- 
--lfdiff: ${LFDIFF_OBJ}
-+lfdiff: libsnet/libsnet.la ${LFDIFF_OBJ}
- 	${CC} ${CFLAGS} -o lfdiff ${LFDIFF_OBJ} ${LDFLAGS}
- 
--repo : ${REPO_OBJ}
-+repo: libsnet/libsnet.la ${REPO_OBJ}
- 	${CC} ${CFLAGS} -o repo ${REPO_OBJ} ${LDFLAGS}
- 
- t2pkg: ${T2PKG_OBJ}
- 	${CC} ${CFLAGS} -o t2pkg ${T2PKG_OBJ} ${LDFLAGS}
- 
--twhich: ${TWHICH_OBJ}
-+twhich: libsnet/libsnet.la ${TWHICH_OBJ}
- 	${CC} ${CFLAGS} -o twhich ${TWHICH_OBJ} ${LDFLAGS}
- 
--lsort: ${LSORT_OBJ}
-+lsort: libsnet/libsnet.la ${LSORT_OBJ}
- 	${CC} ${CFLAGS} -o lsort ${LSORT_OBJ} ${LDFLAGS}
- 
- FRC :
diff -ruN ./files/patch-README ./files/patch-README
--- ./files/patch-README	2014-05-22 14:34:26.000000000 -0400
+++ ./files/patch-README	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
---- ./README.orig	2010-12-12 22:42:49.000000000 -0500
-+++ ./README	2012-03-20 14:37:54.000000000 -0400
-@@ -72,25 +72,25 @@
-   % "env CPPFLAGS=-I/usr/kerberos/include ./configure"
- 
- -----------------
--Building from CVS
-+Building from git
- -----------------
- The Radmind Development Team occasionally asks for help testing a new feature
- or bug fix. The best way to assist is to download the source code from the
--CVS repository and build it manually. The following steps will result in
--a build from CVS.
-+git repository and build it manually. The following steps will result in
-+a build from git.
- 
--1) Download the source from CVS:
-+1) Download the source from git:
- 
--cvs -d :pserver:anonymous@radmind.cvs.sourceforge.net:/cvsroot/radmind \
--	checkout radmind
-+    git clone git://radmind.git.sourceforge.net/gitroot/gradmind
- 
- 2) Move into the new radmind directory:
- 
--cd radmind
-+    cd radmind
- 
--3) Download libsnet[1], the network library Radmind uses:
-+3) Checkout all required submodules [1]:
- 
--sh bin/getsnet
-+    git submodule init
-+    git submodule update
- 
- 4) Follow steps 2 and 3 from "More detailed instructions" for building, above.
- 
-@@ -115,4 +115,7 @@
- ----------
- References
- ----------
--[1]: http://sourceforge.net/projects/libsnet
-+[1]: Current submodules:
-+
-+    * libsnet, a networking library with TLS support
-+	http://sourceforge.net/projects/libsnet
diff -ruN ./files/patch-aclocal.m4 ./files/patch-aclocal.m4
--- ./files/patch-aclocal.m4	2014-05-22 14:34:26.000000000 -0400
+++ ./files/patch-aclocal.m4	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
---- ./aclocal.m4.orig	2010-12-12 22:42:49.000000000 -0500
-+++ ./aclocal.m4	2012-03-20 14:37:54.000000000 -0400
-@@ -105,16 +105,11 @@
- 	    arches="-arch i386 -arch ppc"
- 	    ;;
- 
--	  darwin9*)
-+	  darwin9*|darwin10*|darwin11*)
- 	    dep_target="-mmacosx-version-min=10.4"
- 	    macosx_sdk="MacOSX10.5.sdk"
- 	    arches="-arch i386 -arch x86_64 -arch ppc -arch ppc64"
--	    ;;
--
--	  darwin10*)
--	    dep_target="-mmacosx-version-min=10.4"
--	    macosx_sdk="MacOSX10.6.sdk"
--	    arches="-arch i386 -arch x86_64 -arch ppc"
-+	    LDFLAGS="$LDFLAGS -L/Developer/SDKs/$macosx_sdk/usr/lib"
- 	    ;;
- 
- 	  *)
diff -ruN ./files/patch-configure.ac ./files/patch-configure.ac
--- ./files/patch-configure.ac	2014-05-22 14:34:26.000000000 -0400
+++ ./files/patch-configure.ac	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
---- ./configure.ac.orig	2010-12-12 22:43:38.000000000 -0500
-+++ ./configure.ac	2012-03-20 14:37:54.000000000 -0400
-@@ -45,24 +45,29 @@
- # Check sizes
- AC_CHECK_SIZEOF(off_t)
- 
-+# check early to make any required changes to environment for following tests.
-+CHECK_UNIVERSAL_BINARIES
-+
- # Checks for libraries.
- AC_CHECK_LIB(c, inet_aton, libc_inet_aton=yes) 
- if test x$libc_inet_aton != xyes; then 
-     AC_CHECK_LIB(resolv, inet_aton) 
- fi 
--AC_CHECK_LIB(c, lchown)
--AC_CHECK_LIB(c, lchmod)
-+AC_CHECK_LIB(c, lchown, [AC_DEFINE(HAVE_LCHOWN)], [])
-+AC_CHECK_LIB(c, lchmod, [AC_DEFINE(HAVE_LCHMOD)], [])
- AC_CHECK_LIB(nsl, gethostbyaddr)
- AC_CHECK_LIB([socket], [socket])
- AC_CHECK_LIB([ssl], [SSL_accept], , [CHECK_SSL])
- AC_CHECK_HEADER([openssl/ssl.h], [], [AC_MSG_ERROR([header file <openssl/ssl.h>
- is required for this software.  You may be running RedHat 9.  If so, see the FAQ or the README for further instructions.])])
- AC_CHECK_LIB([crypto], [SSLeay_version], , [CHECK_SSL])
--AC_CHECK_FUNC([X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], [])
-+AC_CHECK_LIB([crypto], [X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], [])
- 
- # PAM
--AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=yes], [Pluggable Authentication Module support (default: yes)]), [], with_pam=yes)
-+AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=PATH], [Pluggable Authentication Module support (default: /usr)]), [], with_pam=/usr)
- if test x_"$with_pam" != x_no; then
-+    CPPFLAGS="${CPPFLAGS} -I$with_pam/include"
-+    LDFLAGS="${LDFLAGS} -L$with_pam/lib"
-     AC_CHECK_LIB([pam], [pam_start],
- 	[
- 	AC_CHECK_HEADERS(pam/pam_appl.h, , [AC_CHECK_HEADERS(security/pam_appl.h)])
-@@ -75,7 +80,6 @@
- AC_CHECK_LIB(dns_sd, DNSServiceRegister)
- 
- CHECK_ZLIB
--CHECK_UNIVERSAL_BINARIES
- 
- # HPUX lacks wait4 and strtoll
- AC_CHECK_FUNCS(wait4 strtoll)
diff -ruN ./files/patch-lapply.c ./files/patch-lapply.c
--- ./files/patch-lapply.c	2014-05-22 14:34:26.000000000 -0400
+++ ./files/patch-lapply.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
---- ./lapply.c.orig	2010-12-12 22:42:49.000000000 -0500
-+++ ./lapply.c	2012-03-20 14:37:54.000000000 -0400
-@@ -651,27 +651,37 @@
- filechecklist:
- 		if ( head == NULL ) {
- 		    if ( unlink( path ) != 0 ) {
--			perror( path );
--			goto error2;
--		    }
--		    if ( !quiet && !showprogress ) {
--			printf( "%s: deleted\n", path );
--		    }
--		    if ( showprogress ) {
--			progressupdate( PROGRESSUNIT, path );
--		    }
--		} else {
--		    if ( ischildcase( path, head->path, case_sensitive )) {
--			if ( unlink( path ) != 0 ) {
-+			if ( !force || errno != ENOENT ) {
- 			    perror( path );
- 			    goto error2;
- 			}
-+			fprintf( stderr, "Warning: failed to remove %s: %s\n",
-+				path, strerror( errno ));
-+		    } else {
- 			if ( !quiet && !showprogress ) {
- 			    printf( "%s: deleted\n", path );
- 			}
- 			if ( showprogress ) {
- 			    progressupdate( PROGRESSUNIT, path );
- 			}
-+		    }
-+		} else {
-+		    if ( ischildcase( path, head->path, case_sensitive )) {
-+			if ( unlink( path ) != 0 ) {
-+			    if ( !force || errno != ENOENT ) {
-+				perror( path );
-+				goto error2;
-+			    }
-+			    fprintf( stderr, "Warning: failed to remove %s: "
-+				    "%s\n", path, strerror( errno ));
-+			} else {
-+			    if ( !quiet && !showprogress ) {
-+				printf( "%s: deleted\n", path );
-+			    }
-+			    if ( showprogress ) {
-+				progressupdate( PROGRESSUNIT, path );
-+			    }
-+			}
- 		    } else {
- 			/* remove head */
- 			if ( rmdir( head->path ) != 0 ) {
diff -ruN ./files/patch-man__lcreate.1 ./files/patch-man__lcreate.1
--- ./files/patch-man__lcreate.1	2014-05-22 14:34:26.000000000 -0400
+++ ./files/patch-man__lcreate.1	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
---- ./man/lcreate.1.orig	2010-12-12 22:50:53.000000000 -0500
-+++ ./man/lcreate.1	2012-03-20 14:38:03.000000000 -0400
-@@ -45,12 +45,6 @@
- .sp
- If the -n option is given, no files or transcripts are uploaded.  Instead,
- .B lcreate
--verifies that all files exist in the filesystem and have
--the same size as listed in the transcript.  If used with the -c option,
--checksums are also verified.
--.sp
--If the -n option is given, no files or transcripts are uploaded.  Instead,
--.B lcreate
- uses 
- .BR access (2)
- to verify that all files in the transcript exist in the
diff -ruN ./files/patch-man__rash.1 ./files/patch-man__rash.1
--- ./files/patch-man__rash.1	2014-05-22 14:34:26.000000000 -0400
+++ ./files/patch-man__rash.1	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
---- ./man/rash.1.orig	2010-12-12 22:50:53.000000000 -0500
-+++ ./man/rash.1	2012-03-20 14:38:08.000000000 -0400
-@@ -11,6 +11,10 @@
- |
- .B -q
- ] [
-+.BR \-C\  "generate"
-+|
-+.BI \-C\  checksum
-+] [
- .B \-D
- .I workingdir
- ] [
-@@ -120,6 +124,24 @@
- .B \-c
- use sha1 checksums.
- .TP 19
-+.BR \-C\  "generate"
-+Print a sha1 checksum of the difference transcript of applied changes. For use with
-+.IR auto ,
-+.IR force
-+or
-+.IR update .
-+.TP 19
-+.BI \-C\  checksum
-+In
-+.I auto
-+mode, exit with an error if the checksum of the difference transcript to be applied does not match
-+.IR checksum .
-+In
-+.I update
-+or
-+.I force
-+mode, warn if the two do not match.
-+.TP 19
- .BI \-D\  workingdir
- change to
- .I workingdir
diff -ruN ./files/patch-mkdirs.c ./files/patch-mkdirs.c
--- ./files/patch-mkdirs.c	2014-05-22 14:34:26.000000000 -0400
+++ ./files/patch-mkdirs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
---- ./mkdirs.c.orig	2010-12-12 22:42:49.000000000 -0500
-+++ ./mkdirs.c	2012-03-20 14:38:08.000000000 -0400
-@@ -37,7 +37,9 @@
- 	if ( mkdir( path, 0777 ) == 0 ) {
- 	    break;
- 	}
--	if ( errno != ENOENT ) {
-+	if ( errno == EEXIST ) {
-+	    break;
-+	} else if ( errno != ENOENT ) {
- 	    return( -1 );
- 	}
- 	q = p;
diff -ruN ./files/patch-ra.sh ./files/patch-ra.sh
--- ./files/patch-ra.sh	2014-05-22 14:34:26.000000000 -0400
+++ ./files/patch-ra.sh	1969-12-31 19:00:00.000000000 -0500
@@ -1,139 +0,0 @@
---- ./ra.sh.orig	2010-12-12 22:42:49.000000000 -0500
-+++ ./ra.sh	2012-03-20 14:38:08.000000000 -0400
-@@ -91,7 +91,7 @@
- }
- 
- usage() {
--    $ECHO "Usage:	$0 [ -ctV ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2
-+    $ECHO "Usage:	$0 [ -cIltV ] [ -% | -q ] [ -C \"generate\" | -C <checksum> ] [ -D working-directory ] [ -h server ] [ -p port ] [ -w authlevel ] { trip | update | create | auto | force | checkout | checkin } [ /path/or/file ]" >&2
-     exit 1
- }
- 
-@@ -128,6 +128,38 @@
-     fi
- }
- 
-+cksum_generate() {
-+    if [ -n "$FSDIFF_CHECKSUM" ]; then
-+	FTMP_CHECKSUM=`openssl sha1 ${FTMP} | awk '{ print $2 }'`
-+    fi
-+}
-+
-+cksum_compare() {
-+    if [ -n "$FSDIFF_CHECKSUM" -a \
-+	    "$FSDIFF_CHECKSUM" != "generate" -a \
-+	    "$FSDIFF_CHECKSUM" != "$FTMP_CHECKSUM" ]; then
-+	return 1
-+    fi
-+
-+    return 0
-+}
-+
-+cksum_print() {
-+    if [ -n "$FSDIFF_CHECKSUM" ]; then
-+	$ECHO "Difference transcript checksum: $FTMP_CHECKSUM"
-+    fi
-+}
-+
-+cksum_mismatch() {
-+    if [ -n "$FSDIFF_CHECKSUM" ]; then
-+	$ECHO
-+	$ECHO "**** Difference transcript checksum mismatch!"
-+	$ECHO "****	Expected: $FSDIFF_CHECKSUM"
-+	$ECHO "****	Actual:   $FTMP_CHECKSUM"
-+	#ECHO
-+    fi
-+}
-+
- update() {
-     opt="$1"
-     kopt=
-@@ -211,6 +243,11 @@
-     fi
-     if [ x"${opt}" = x"interactive" ]; then
- 	while [ 1 ]; do
-+	    cksum_generate
-+	    if ! cksum_compare; then
-+		cksum_mismatch
-+	    fi
-+
- 	    if [ x"${can_edit}" = x"yes" ]; then
- 		$ECHO -n "(e)dit difference transcript, "
- 	    fi
-@@ -248,7 +285,8 @@
- 		
-     lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP}
-     case "$?" in
--    0)	;;
-+    0)	cksum_print
-+	;;
- 
-     *)  if [ x"$opt" = x"hook" ]; then
- 	    $ECHO -n "Applying changes failed, trying again "
-@@ -284,7 +322,7 @@
-     . "${DEFAULTS}"
- fi
- 
--while getopts %cD:h:Ilp:qr:tU:Vw: opt; do
-+while getopts %C:cD:h:Ilp:qr:tU:Vw: opt; do
-     case $opt in
-     %)  PROGRESS="-%"
- 	FPROGRESS="-%"
-@@ -293,6 +331,13 @@
-     q)  PROGRESS="-q"
- 	;;
- 
-+    C)	FSDIFF_CHECKSUM="$OPTARG"
-+	if ! type openssl >/dev/null 2>&1; then
-+	    $ECHO "-C requires openssl, but no openssl found in PATH $PATH"
-+	    cleanup_and_exit
-+	fi
-+	;;
-+
-     c)	CHECKSUM="-csha1"
- 	;;
- 
-@@ -524,6 +569,14 @@
- 		cleanup
- 		exit 1
- 	    fi
-+
-+	    cksum_generate
-+	    if ! cksum_compare; then
-+		$ECHO "Auto failure: `hostname`: difference cksum mismatch" 
-+		cksum_mismatch
-+		cleanup_and_exit
-+	    fi
-+
- 	    dopreapply ${FTMP}
- 	    if [ -s ${FTMP} ]; then
- 		lapply ${NETOPTS} ${CASE} ${PROGRESS} \
-@@ -532,6 +585,7 @@
- 		0)
- 		    $ECHO Auto update: `hostname`
- 		    cat ${FTMP}
-+		    cksum_print
- 		    dopostapply ${FTMP}
- 		    cleanup
- 		    break
-@@ -588,14 +642,17 @@
- 	exit 0
-     fi
-     
-+    cksum_generate
-+    cksum_compare || cksum_mismatch
-     dopreapply ${FTMP}
-     lapply ${CASE} ${PROGRESS} ${NETOPTS} ${CHECKSUM} ${FTMP}
-     case "$?" in
--    0)	;;
-+    0)	cksum_print
-+	;;
- 
-     *)	cleanup
--	    exit $?
--	    ;;
-+	exit $?
-+	;;
-     esac
-     dopostapply ${FTMP}
-     
diff -ruN ./files/patch-t2pkg.c ./files/patch-t2pkg.c
--- ./files/patch-t2pkg.c	2014-05-22 14:34:26.000000000 -0400
+++ ./files/patch-t2pkg.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
---- ./t2pkg.c.orig	2010-12-12 22:42:49.000000000 -0500
-+++ ./t2pkg.c	2012-03-20 14:38:08.000000000 -0400
-@@ -38,6 +38,7 @@
- extern off_t	lsize;
- extern char	*version;
- 
-+int		tran_format = -1;
- int		cksum = 0;
- int		force = 0;
- int		case_sensitive = 1;
-@@ -718,31 +719,23 @@
- 	}
- 
- 	/* create the destination path */
--	if ( snprintf( tmp, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name )
-+	if ( snprintf( dst, MAXPATHLEN, "%s/%s", dstdir, t->t_pinfo.pi_name )
- 		>= MAXPATHLEN ) {
- 	    fprintf( stderr, "%s/%s: path too long\n", dstdir,
- 			t->t_pinfo.pi_name );
- 	    exit( 2 );
- 	}
--	if ( mkdirs( tmp ) < 0 ) {
--	    fprintf( stderr, "mkdirs %s: %s\n", tmp, strerror( errno ));
--	}
--	if ( realpath( tmp, dst ) == NULL ) {
--	    fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno ));
--	    exit( 2 );
-+	if ( mkdirs( dst ) < 0 ) {
-+	    fprintf( stderr, "mkdirs %s: %s\n", dst, strerror( errno ));
- 	}
- 
- 	/* and the source path */
--	if ( snprintf( tmp, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name )
-+	if ( snprintf( src, MAXPATHLEN, "%s/%s", root, t->t_pinfo.pi_name )
- 		>= MAXPATHLEN ) {
- 	    fprintf( stderr, "%s/%s: path too long\n", dstdir,
- 			t->t_pinfo.pi_name );
- 	    exit( 2 );
- 	}
--	if ( realpath( tmp, src ) == NULL ) {
--	    fprintf( stderr, "realpath %s: %s\n", tmp, strerror( errno ));
--	    exit( 2 );
--	}
- 
- 	if ( local_update( t, dst, src, where ) != 0 ) {
- 	    /* XXX is this really a good idea? */
diff -ruN ./pkg-descr ./pkg-descr
--- ./pkg-descr	2014-05-22 14:34:26.000000000 -0400
+++ ./pkg-descr	2014-05-22 14:17:53.000000000 -0400
@@ -3,4 +3,6 @@
 of hosts at the filesystem level. It can also act as an intelligent
 tripwire.
 
-WWW:	http://rsug.itd.umich.edu/software/radmind/
+This port contains security and functionality patches through May 22, 2014.
+
+WWW:	http://sourceforge.net/projects/radmind/
diff -ruN ./pkg-plist ./pkg-plist
--- ./pkg-plist	2014-05-22 14:34:26.000000000 -0400
+++ ./pkg-plist	2014-05-22 13:11:03.000000000 -0400
@@ -10,18 +10,30 @@
 bin/repo
 bin/twhich
 sbin/radmind
+man/man1/fsdiff.1.gz
+man/man1/ktcheck.1.gz
+man/man1/lapply.1.gz
+man/man1/lcksum.1.gz
+man/man1/lcreate.1.gz
+man/man1/lfdiff.1.gz
+man/man1/lmerge.1.gz
+man/man1/lsort.1.gz
+man/man1/rash.1.gz
+man/man1/repo.1.gz
+man/man1/twhich.1.gz
+man/man5/applefile.5.gz
+man/man8/radmind.8.gz
 %%PORTDOCS%%%%DOCSDIR%%/COPYRIGHT
 %%PORTDOCS%%%%DOCSDIR%%/README
 %%PORTDOCS%%%%DOCSDIR%%/SPEC
-%%PORTDOCS%%@dirrm %%DOCSDIR%%
-@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%
-@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/cert
-@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/client
-@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/preapply
-@exec mkdir -p -m 755 %%RADMIND_BASE_DIR%%/postapply
-@exec chown -R %%RADMINUSER%%:%%RADMINUSER%% %%RADMIND_BASE_DIR%%
-@unexec if cmp -s %%RADMIND_BASE_DIR%%/config.sample %%RADMIND_BASE_DIR%%/config; then rm -f %%RADMIND_BASE_DIR%%/config; fi
+%%PORTDOCS%%
+@mode 700
 %%RADMIND_BASE_DIR%%/config.sample
+@mode
+@exec chown -R %%RADMINUSER%% %%RADMIND_BASE_DIR%%
+@exec chgrp -R %%RADMINUSER%% %%RADMIND_BASE_DIR%%
+
+@unexec if cmp -s %%RADMIND_BASE_DIR%%/config.sample %%RADMIND_BASE_DIR%%/config; then rm -f %%RADMIND_BASE_DIR%%/config; fi
 @dirrmtry %%RADMIND_BASE_DIR%%/transcript
 @dirrmtry %%RADMIND_BASE_DIR%%/tmp/transcript
 @dirrmtry %%RADMIND_BASE_DIR%%/tmp/file


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405221854.s4MIsM88029312>