Subject: rdist (#243)
Index:	ucb/rdist/* 2.11BSD

Description:
	rdist runs out of memory so quickly that the program is
	essentially useless.

Repeat-By:
	Try to use rdist to keep two 2.11BSD systems synchronized.

Fix:
	Thanks to Tom Helbekkmo (tih@nhh.no) for trimming rdist's
	appetite for memory.  The problem was rdist allocating a 2kb
	structure too often instead of allocating just what was needed
	_when_ it was needed.

	Naturally I could not leave well enough alone ;-)  By employing
	'xstr' to share repeated strings over 2kb of D-space was freed.

	The variadic functions were converted to use <varargs.h>.

	You will need to have the current version of 'yacc' (patch #241)
	installed on the system or errors will result when compiling the
	yacc generated gram.c file.

	1) Save the patch to a file - /tmp/243
	2) patch -p0 < /tmp/243
	3) cd /usr/src/ucb/rdist
	4) make
	   make install
	   make clean
=============================cut here====================
*** /usr/src/ucb/rdist/Makefile.old	Mon Jul 11 10:28:05 1994
--- /usr/src/ucb/rdist/Makefile	Thu May 11 22:56:01 1995
***************
*** 3,24 ****
  # All rights reserved.  The Berkeley software License Agreement
  # specifies the terms and conditions for redistribution.
  #
! #	@(#)Makefile	5.1.1 (2.11BSD GTE) 7/11/94
  #
  DESTDIR=
  SEPFLAG= -i
  SRCS =	docmd.c expand.c gram.y lookup.c main.c server.c
  OBJS =	docmd.o expand.o gram.o lookup.o main.o server.o
! LINT =	lint -ps
  CFLAGS= -O
  
! rdist:	${OBJS}
! 	${CC} ${SEPFLAG} -o rdist ${OBJS}
  
  ${OBJS}:  defs.h
  
  clean:
! 	rm -f *.o gram.c errs rdist
  
  install: rdist
  	install -s -m 4751 rdist ${DESTDIR}/usr/ucb/rdist
--- 3,42 ----
  # All rights reserved.  The Berkeley software License Agreement
  # specifies the terms and conditions for redistribution.
  #
! #	@(#)Makefile	5.1.3 (2.11BSD GTE) 1995/05/11
  #
  DESTDIR=
  SEPFLAG= -i
+ XSTR=	xstr
+ YACC=	yacc
  SRCS =	docmd.c expand.c gram.y lookup.c main.c server.c
  OBJS =	docmd.o expand.o gram.o lookup.o main.o server.o
! LINT =	lint -ha
  CFLAGS= -O
  
! .c.o:
! 	${CC} -E ${CFLAGS} $*.c | ${XSTR} -c -
! 	${CC} ${CFLAGS} -c x.c
! 	mv -f x.o $*.o
! 	rm -f x.c
  
+ rdist:	${OBJS} strings.o
+ 	${CC} ${SEPFLAG} -o rdist ${OBJS} strings.o
+ 
  ${OBJS}:  defs.h
  
+ strings.o: strings
+ 	${XSTR}
+ 	${CC} -c xs.c
+ 	mv -f xs.o strings.o
+ 	rm -f xs.c
+ 
+ gram.c: gram.y
+ 	${YACC} gram.y
+ 	mv y.tab.c gram.c
+ 
  clean:
! 	rm -f ${OBJS} gram.c errs rdist strings strings.o x.c xs.c y.tab.c
  
  install: rdist
  	install -s -m 4751 rdist ${DESTDIR}/usr/ucb/rdist
*** /usr/src/ucb/rdist/defs.h.old	Sat Jun 11 17:59:04 1994
--- /usr/src/ucb/rdist/defs.h	Tue May  9 23:01:23 1995
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)defs.h	5.2.1 (2.11BSD GTE) 6/11/95
   */
  
  #include <stdio.h>
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)defs.h	5.2.2 (2.11BSD GTE) 1995/05/09
   */
  
  #include <stdio.h>
***************
*** 97,104 ****
  	ino_t	inum;
  	dev_t	devnum;
  	int	count;
! 	char	pathname[BUFSIZ];
! 	char	target[BUFSIZ];
  	struct	linkbuf *nextp;
  };
  
--- 97,104 ----
  	ino_t	inum;
  	dev_t	devnum;
  	int	count;
! 	char	*pathname;
! 	char	*target;
  	struct	linkbuf *nextp;
  };
  
***************
*** 110,116 ****
  extern int nerrs;		/* number of errors seen */
  extern int rem;			/* remote file descriptor */
  extern int iamremote;		/* acting as remote server */
! extern char tmpfile[];		/* file name for logging changes */
  extern struct linkbuf *ihead;	/* list of files with more than one link */
  extern struct passwd *pw;	/* pointer to static area used by getpwent */
  extern struct group *gr;	/* pointer to static area used by getgrent */
--- 110,116 ----
  extern int nerrs;		/* number of errors seen */
  extern int rem;			/* remote file descriptor */
  extern int iamremote;		/* acting as remote server */
! extern char tempfile[];		/* file name for logging changes */
  extern struct linkbuf *ihead;	/* list of files with more than one link */
  extern struct passwd *pw;	/* pointer to static area used by getpwent */
  extern struct group *gr;	/* pointer to static area used by getgrent */
***************
*** 117,123 ****
  extern char host[];		/* host name of master copy */
  extern char buf[];		/* general purpose buffer */
  extern int errno;		/* system error number */
! extern char *sys_errlist[];
  
  char *makestr();
  struct namelist *makenl();
--- 117,123 ----
  extern char host[];		/* host name of master copy */
  extern char buf[];		/* general purpose buffer */
  extern int errno;		/* system error number */
! extern char *strerror();
  
  char *makestr();
  struct namelist *makenl();
*** /usr/src/ucb/rdist/docmd.c.old	Mon Jun 13 22:05:14 1994
--- /usr/src/ucb/rdist/docmd.c	Tue May  9 23:02:19 1995
***************
*** 5,11 ****
   */
  
  #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)docmd.c	5.1.1 (2.11BSD GTE) 6/11/94";
  #endif
  
  #include "pathnames.h"
--- 5,11 ----
   */
  
  #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)docmd.c	5.1.2 (2.11BSD GTE) 1995/05/09";
  #endif
  
  #include "pathnames.h"
***************
*** 107,114 ****
  		signal(SIGPIPE, lostconn);
  		if (!makeconn(rhost))
  			return;
! 		if ((lfp = fopen(tmpfile, "w")) == NULL) {
! 			fatal("cannot open %s\n", tmpfile);
  			exit(1);
  		}
  	}
--- 107,114 ----
  		signal(SIGPIPE, lostconn);
  		if (!makeconn(rhost))
  			return;
! 		if ((lfp = fopen(tempfile, "w")) == NULL) {
! 			fatal("cannot open %s\n", tempfile);
  			exit(1);
  		}
  	}
***************
*** 142,151 ****
  	}
  	for (sc = cmds; sc != NULL; sc = sc->sc_next)
  		if (sc->sc_type == NOTIFY)
! 			notify(tmpfile, rhost, sc->sc_args, 0);
  	if (!nflag) {
! 		(void) unlink(tmpfile);
  		for (; ihead != NULL; ihead = ihead->nextp) {
  			free(ihead);
  			if ((opts & IGNLNKS) || ihead->count == 0)
  				continue;
--- 142,153 ----
  	}
  	for (sc = cmds; sc != NULL; sc = sc->sc_next)
  		if (sc->sc_type == NOTIFY)
! 			notify(tempfile, rhost, sc->sc_args, 0);
  	if (!nflag) {
! 		(void) unlink(tempfile);
  		for (; ihead != NULL; ihead = ihead->nextp) {
+ 			if (ihead->pathname) free(ihead->pathname);
+ 			if (ihead->target) free(ihead->target);
  			free(ihead);
  			if ((opts & IGNLNKS) || ihead->count == 0)
  				continue;
***************
*** 308,314 ****
  		return;
  	}
  	if (stat(stamp, &stb) < 0) {
! 		error("%s: %s\n", stamp, sys_errlist[errno]);
  		return;
  	}
  	if (debug)
--- 310,316 ----
  		return;
  	}
  	if (stat(stamp, &stb) < 0) {
! 		error("%s: %s\n", stamp, strerror(errno));
  		return;
  	}
  	if (debug)
***************
*** 319,326 ****
  	if (nflag || (options & VERIFY))
  		tfp = NULL;
  	else {
! 		if ((tfp = fopen(tmpfile, "w")) == NULL) {
! 			error("%s: %s\n", stamp, sys_errlist[errno]);
  			return;
  		}
  		(void) gettimeofday(&tv[0], &tz);
--- 321,328 ----
  	if (nflag || (options & VERIFY))
  		tfp = NULL;
  	else {
! 		if ((tfp = fopen(tempfile, "w")) == NULL) {
! 			error("%s: %s\n", stamp, strerror(errno));
  			return;
  		}
  		(void) gettimeofday(&tv[0], &tz);
***************
*** 344,352 ****
  		(void) fclose(tfp);
  	for (sc = cmds; sc != NULL; sc = sc->sc_next)
  		if (sc->sc_type == NOTIFY)
! 			notify(tmpfile, NULL, sc->sc_args, lastmod);
  	if (!nflag && !(options & VERIFY))
! 		(void) unlink(tmpfile);
  }
  
  /*
--- 346,354 ----
  		(void) fclose(tfp);
  	for (sc = cmds; sc != NULL; sc = sc->sc_next)
  		if (sc->sc_type == NOTIFY)
! 			notify(tempfile, NULL, sc->sc_args, lastmod);
  	if (!nflag && !(options & VERIFY))
! 		(void) unlink(tempfile);
  }
  
  /*
***************
*** 379,385 ****
  			tp++;
  	}
  	if (access(name, 4) < 0 || stat(name, &stb) < 0) {
! 		error("%s: %s\n", name, sys_errlist[errno]);
  		return;
  	}
  
--- 381,387 ----
  			tp++;
  	}
  	if (access(name, 4) < 0 || stat(name, &stb) < 0) {
! 		error("%s: %s\n", name, strerror(errno));
  		return;
  	}
  
***************
*** 413,419 ****
  		printf("rcmptime(%x)\n", st);
  
  	if ((d = opendir(target)) == NULL) {
! 		error("%s: %s\n", target, sys_errlist[errno]);
  		return;
  	}
  	otp = tp;
--- 415,421 ----
  		printf("rcmptime(%x)\n", st);
  
  	if ((d = opendir(target)) == NULL) {
! 		error("%s: %s\n", target, strerror(errno));
  		return;
  	}
  	otp = tp;
***************
*** 421,427 ****
  	while (dp = readdir(d)) {
  		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
  			continue;
! 		if (len + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
  			error("%s/%s: Name too long\n", target, dp->d_name);
  			continue;
  		}
--- 423,429 ----
  	while (dp = readdir(d)) {
  		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
  			continue;
! 		if (len + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) {
  			error("%s/%s: Name too long\n", target, dp->d_name);
  			continue;
  		}
***************
*** 464,474 ****
  		return;
  
  	if ((fd = open(file, 0)) < 0) {
! 		error("%s: %s\n", file, sys_errlist[errno]);
  		return;
  	}
  	if (fstat(fd, &stb) < 0) {
! 		error("%s: %s\n", file, sys_errlist[errno]);
  		(void) close(fd);
  		return;
  	}
--- 466,476 ----
  		return;
  
  	if ((fd = open(file, 0)) < 0) {
! 		error("%s: %s\n", file, strerror(errno));
  		return;
  	}
  	if (fstat(fd, &stb) < 0) {
! 		error("%s: %s\n", file, strerror(errno));
  		(void) close(fd);
  		return;
  	}
***************
*** 557,577 ****
  			if (re_exec(file) > 0)
  				return(1);
  		}
- 	}
- 	return(0);
- }
- 
- char *
- colon(cp)
- 	register char *cp;
- {
- 
- 	while (*cp) {
- 		if (*cp == ':')
- 			return(cp);
- 		if (*cp == '/')
- 			return(0);
- 		cp++;
  	}
  	return(0);
  }
--- 559,564 ----
*** /usr/src/ucb/rdist/expand.c.old	Mon Feb 16 22:09:49 1987
--- /usr/src/ucb/rdist/expand.c	Tue May  9 20:56:16 1995
***************
*** 4,12 ****
   * specifies the terms and conditions for redistribution.
   */
  
! #ifndef lint
! static char sccsid[] = "@(#)expand.c	5.2 (Berkeley) 3/28/86";
! #endif not lint
  
  #include "defs.h"
  
--- 4,12 ----
   * specifies the terms and conditions for redistribution.
   */
  
! #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)expand.c	5.2.1 (2.11BSD) 1995/05/09";
! #endif
  
  #include "defs.h"
  
***************
*** 14,20 ****
  #define LC '{'
  #define RC '}'
  
! static char	shchars[] = "${[*?";
  
  int	which;		/* bit mask of types to expand */
  int	eargc;		/* expanded arg count */
--- 14,20 ----
  #define LC '{'
  #define RC '}'
  
! static char	*shchars = "${[*?";
  
  int	which;		/* bit mask of types to expand */
  int	eargc;		/* expanded arg count */
***************
*** 258,264 ****
  {
  	struct stat stb;
  	register struct direct *dp;
! 	DIR *dirp;
  
  	dirp = opendir(path);
  	if (dirp == NULL) {
--- 258,264 ----
  {
  	struct stat stb;
  	register struct direct *dp;
! 	register DIR *dirp;
  
  	dirp = opendir(path);
  	if (dirp == NULL) {
***************
*** 289,295 ****
  	closedir(dirp);
  patherr2:
  	strcat(path, ": ");
! 	strcat(path, sys_errlist[errno]);
  	yyerror(path);
  }
  
--- 289,295 ----
  	closedir(dirp);
  patherr2:
  	strcat(path, ": ");
! 	strcat(path, strerror(errno));
  	yyerror(path);
  }
  
***************
*** 575,581 ****
  char *
  exptilde(buf, file)
  	char buf[];
! 	register char *file;
  {
  	register char *s1, *s2, *s3;
  	extern char homedir[];
--- 575,581 ----
  char *
  exptilde(buf, file)
  	char buf[];
! 	char *file;
  {
  	register char *s1, *s2, *s3;
  	extern char homedir[];
*** /usr/src/ucb/rdist/gram.y.old	Mon Feb 16 22:09:48 1987
--- /usr/src/ucb/rdist/gram.y	Tue May  9 20:59:00 1995
***************
*** 5,12 ****
   * specifies the terms and conditions for redistribution.
   */
  
! #ifndef lint
! static	char *sccsid = "@(#)gram.y	5.2 (Berkeley) 85/06/21";
  #endif
  
  #include "defs.h"
--- 5,12 ----
   * specifies the terms and conditions for redistribution.
   */
  
! #if	!defined(lint) && defined(DOSCCS)
! static	char *sccsid = "@(#)gram.y	5.2.1 (2.11BSD) 1995/05/09";
  #endif
  
  #include "defs.h"
***************
*** 173,179 ****
  	static char yytext[INMAX];
  	register int c;
  	register char *cp1, *cp2;
! 	static char quotechars[] = "[]{}*?$";
  	
  again:
  	switch (c = getc(fin)) {
--- 173,179 ----
  	static char yytext[INMAX];
  	register int c;
  	register char *cp1, *cp2;
! 	static char *quotechars = "[]{}*?$";
  	
  again:
  	switch (c = getc(fin)) {
*** /usr/src/ucb/rdist/lookup.c.old	Mon Feb 16 22:09:49 1987
--- /usr/src/ucb/rdist/lookup.c	Tue May  9 19:50:11 1995
***************
*** 4,12 ****
   * specifies the terms and conditions for redistribution.
   */
  
! #ifndef lint
! static char sccsid[] = "@(#)lookup.c	5.1 (Berkeley) 6/6/85";
! #endif not lint
  
  #include "defs.h"
  
--- 4,12 ----
   * specifies the terms and conditions for redistribution.
   */
  
! #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)lookup.c	5.1.1 (2.11BSD) 1995/05/09";
! #endif
  
  #include "defs.h"
  
*** /usr/src/ucb/rdist/main.c.old	Mon Feb 16 22:09:48 1987
--- /usr/src/ucb/rdist/main.c	Wed May 10 08:19:13 1995
***************
*** 4,19 ****
   * specifies the terms and conditions for redistribution.
   */
  
! #ifndef lint
  char copyright[] =
  "@(#) Copyright (c) 1983 Regents of the University of California.\n\
   All rights reserved.\n";
- #endif not lint
  
! #ifndef lint
! static char sccsid[] = "@(#)main.c	5.1 (Berkeley) 6/6/85";
! #endif not lint
  
  #include "defs.h"
  
  #define NHOSTS 100
--- 4,18 ----
   * specifies the terms and conditions for redistribution.
   */
  
! #if	!defined(lint) && defined(DOSCCS)
  char copyright[] =
  "@(#) Copyright (c) 1983 Regents of the University of California.\n\
   All rights reserved.\n";
  
! static char sccsid[] = "@(#)main.c	5.1.1 (2.11BSD) 1995/05/09";
! #endif
  
+ #include <paths.h>
  #include "defs.h"
  
  #define NHOSTS 100
***************
*** 23,30 ****
   */
  
  char	*distfile = NULL;
! char	tmpfile[] = "/tmp/rdistXXXXXX";
! char	*tmpname = &tmpfile[5];
  
  int	debug;		/* debugging flag */
  int	nflag;		/* NOP flag, just print commands without executing */
--- 22,31 ----
   */
  
  char	*distfile = NULL;
! #define	_RDIST_TMP	"/rdistXXXXXX"
! /* Can't use "sizeof (_PATH_TMP) + sizeof (_RDIST_TMP) + 1" because of xstr */
! char	tempfile[24];
! char	*tempname;
  
  int	debug;		/* debugging flag */
  int	nflag;		/* NOP flag, just print commands without executing */
***************
*** 34,42 ****
  
  FILE	*fin = NULL;	/* input file pointer */
  int	rem = -1;	/* file descriptor to remote source/sink process */
! char	host[32];	/* host name */
  int	nerrs;		/* number of errors while sending/receiving */
! char	user[10];	/* user's name */
  char	homedir[128];	/* user's home directory */
  int	userid;		/* user's user ID */
  int	groupid;	/* user's group ID */
--- 35,43 ----
  
  FILE	*fin = NULL;	/* input file pointer */
  int	rem = -1;	/* file descriptor to remote source/sink process */
! char	host[MAXHOSTNAMELEN];	/* host name */
  int	nerrs;		/* number of errors while sending/receiving */
! char	user[20];	/* user's name */
  char	homedir[128];	/* user's home directory */
  int	userid;		/* user's user ID */
  int	groupid;	/* user's group ID */
***************
*** 61,66 ****
--- 62,70 ----
  	strcpy(homedir, pw->pw_dir);
  	groupid = pw->pw_gid;
  	gethostname(host, sizeof(host));
+ 	strcpy(tempfile, _PATH_TMP);
+ 	strcat(tempfile, _RDIST_TMP);
+ 	tempname = rindex(tempfile, '/') + 1;
  
  	while (--argc > 0) {
  		if ((arg = *++argv)[0] != '-')
***************
*** 152,158 ****
  	*hp = NULL;
  
  	setreuid(0, userid);
! 	mktemp(tmpfile);
  
  	if (iamremote) {
  		server();
--- 156,162 ----
  	*hp = NULL;
  
  	setreuid(0, userid);
! 	mktemp(tempfile);
  
  	if (iamremote) {
  		server();
***************
*** 255,269 ****
  		nl = nl->n_next;
  	}
  	printf(")\n");
- }
- 
- /*VARARGS*/
- warn(fmt, a1, a2,a3)
- 	char *fmt;
- {
- 	extern int yylineno;
- 
- 	fprintf(stderr, "rdist: line %d: Warning: ", yylineno);
- 	fprintf(stderr, fmt, a1, a2, a3);
- 	fputc('\n', stderr);
  }
--- 259,262 ----
*** /usr/src/ucb/rdist/server.c.old	Thu May 25 22:35:01 1989
--- /usr/src/ucb/rdist/server.c	Wed May 10 09:28:09 1995
***************
*** 4,16 ****
   * specifies the terms and conditions for redistribution.
   */
  
! #ifndef lint
! static char sccsid[] = "@(#)server.c	5.3 (Berkeley) 6/7/86";
! #endif not lint
  
  #include "defs.h"
  
! #define	ack() 	(void) write(rem, "\0\n", 2)
  #define	err() 	(void) write(rem, "\1\n", 2)
  
  struct	linkbuf *ihead;		/* list of files with more than one link */
--- 4,22 ----
   * specifies the terms and conditions for redistribution.
   */
  
! #if	!defined(lint) && defined(DOSCCS)
! static char sccsid[] = "@(#)server.c	5.3.1 (2.11BSD) 1995/05/09";
! #endif
  
  #include "defs.h"
  
! /*
!  * Need to do this because the string "\0\n" was being mangled by xstr.  Besides
!  * this makes for smaller code anyways by avoiding inlining a 3 arg write call.
! */
! static char ack2ch[2] = {'\0', '\n'};
! void ack() { (void) write(rem, ack2ch, 2); }
! 
  #define	err() 	(void) write(rem, "\1\n", 2)
  
  struct	linkbuf *ihead;		/* list of files with more than one link */
***************
*** 272,278 ****
  	if (except(target))
  		return;
  	if ((opts & FOLLOW ? stat(target, &stb) : lstat(target, &stb)) < 0) {
! 		error("%s: %s\n", target, sys_errlist[errno]);
  		return;
  	}
  	if ((u = update(rname, opts, &stb)) == 0) {
--- 278,284 ----
  	if (except(target))
  		return;
  	if ((opts & FOLLOW ? stat(target, &stb) : lstat(target, &stb)) < 0) {
! 		error("%s: %s\n", target, strerror(errno));
  		return;
  	}
  	if ((u = update(rname, opts, &stb)) == 0) {
***************
*** 305,311 ****
  	switch (stb.st_mode & S_IFMT) {
  	case S_IFDIR:
  		if ((d = opendir(target)) == NULL) {
! 			error("%s: %s\n", target, sys_errlist[errno]);
  			return;
  		}
  		(void) sprintf(buf, "D%o %04o 0 0 %s %s %s\n", opts,
--- 311,317 ----
  	switch (stb.st_mode & S_IFMT) {
  	case S_IFDIR:
  		if ((d = opendir(target)) == NULL) {
! 			error("%s: %s\n", target, strerror(errno));
  			return;
  		}
  		(void) sprintf(buf, "D%o %04o 0 0 %s %s %s\n", opts,
***************
*** 327,333 ****
  			if (!strcmp(dp->d_name, ".") ||
  			    !strcmp(dp->d_name, ".."))
  				continue;
! 			if (len + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
  				error("%s/%s: Name too long\n", target,
  					dp->d_name);
  				continue;
--- 333,339 ----
  			if (!strcmp(dp->d_name, ".") ||
  			    !strcmp(dp->d_name, ".."))
  				continue;
! 			if (len + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) {
  				error("%s/%s: Name too long\n", target,
  					dp->d_name);
  				continue;
***************
*** 355,361 ****
  
  			if ((lp = savelink(&stb)) != NULL) {
  				/* install link */
! 				if (*lp->target == 0)
  				(void) sprintf(buf, "k%o %s %s\n", opts,
  					lp->pathname, rname);
  				else
--- 361,367 ----
  
  			if ((lp = savelink(&stb)) != NULL) {
  				/* install link */
! 				if (lp->target == NULL)
  				(void) sprintf(buf, "k%o %s %s\n", opts,
  					lp->pathname, rname);
  				else
***************
*** 403,409 ****
  
  		if ((lp = savelink(&stb)) != NULL) {
  			/* install link */
! 			if (*lp->target == 0)
  			(void) sprintf(buf, "k%o %s %s\n", opts,
  				lp->pathname, rname);
  			else
--- 409,415 ----
  
  		if ((lp = savelink(&stb)) != NULL) {
  			/* install link */
! 			if (lp->target == NULL)
  			(void) sprintf(buf, "k%o %s %s\n", opts,
  				lp->pathname, rname);
  			else
***************
*** 418,424 ****
  	}
  
  	if ((f = open(target, 0)) < 0) {
! 		error("%s: %s\n", target, sys_errlist[errno]);
  		return;
  	}
  	(void) sprintf(buf, "R%o %o %ld %ld %s %s %s\n", opts,
--- 424,430 ----
  	}
  
  	if ((f = open(target, 0)) < 0) {
! 		error("%s: %s\n", target, strerror(errno));
  		return;
  	}
  	(void) sprintf(buf, "R%o %o %ld %ld %s %s %s\n", opts,
***************
*** 434,439 ****
--- 440,446 ----
  	sizerr = 0;
  	for (i = 0; i < stb.st_size; i += BUFSIZ) {
  		int amt = BUFSIZ;
+ 
  		if (i + amt > stb.st_size)
  			amt = stb.st_size - i;
  		if (sizerr == 0 && read(f, buf, amt) != amt)
***************
*** 470,479 ****
  
  struct linkbuf *
  savelink(stp)
! 	struct stat *stp;
  {
! 	struct linkbuf *lp;
! 	int found = 0;
  
  	for (lp = ihead; lp != NULL; lp = lp->nextp)
  		if (lp->inum == stp->st_ino && lp->devnum == stp->st_dev) {
--- 477,485 ----
  
  struct linkbuf *
  savelink(stp)
! 	register struct stat *stp;
  {
! 	register struct linkbuf *lp;
  
  	for (lp = ihead; lp != NULL; lp = lp->nextp)
  		if (lp->inum == stp->st_ino && lp->devnum == stp->st_dev) {
***************
*** 484,489 ****
--- 490,505 ----
  	if (lp == NULL)
  		log(lfp, "out of memory, link information lost\n");
  	else {
+ 		lp->pathname = malloc(strlen(target)+1);
+ 		if (Tdest)
+ 			lp->target = malloc(strlen(Tdest)+1);
+ 		if ((lp->pathname == NULL) || (Tdest && (lp->target == NULL))) {
+ 			log(lfp, "out of memory, link information lost\n");
+ 			if (lp->pathname) free(lp->pathname);
+ 			if (lp->target) free(lp->target);
+ 			free(lp);
+ 			return(NULL);
+ 		}
  		lp->nextp = ihead;
  		ihead = lp;
  		lp->inum = stp->st_ino;
***************
*** 493,499 ****
  		if (Tdest)
  			strcpy(lp->target, Tdest);
  		else
! 			*lp->target = 0;
  	}
  	return(NULL);
  }
--- 509,515 ----
  		if (Tdest)
  			strcpy(lp->target, Tdest);
  		else
! 			lp->target = NULL;
  	}
  	return(NULL);
  }
***************
*** 506,516 ****
  update(rname, opts, stp)
  	char *rname;
  	int opts;
! 	struct stat *stp;
  {
  	register char *cp, *s;
! 	register off_t size;
! 	register time_t mtime;
  
  	if (debug) 
  		printf("update(%s, %x, %x)\n", rname, opts, stp);
--- 522,532 ----
  update(rname, opts, stp)
  	char *rname;
  	int opts;
! 	register struct stat *stp;
  {
  	register char *cp, *s;
! 	off_t size;
! 	time_t mtime;
  
  	if (debug) 
  		printf("update(%s, %x, %x)\n", rname, opts, stp);
***************
*** 614,620 ****
  		if (errno == ENOENT)
  			(void) write(rem, "N\n", 2);
  		else
! 			error("%s:%s: %s\n", host, target, sys_errlist[errno]);
  		*tp = '\0';
  		return;
  	}
--- 630,636 ----
  		if (errno == ENOENT)
  			(void) write(rem, "N\n", 2);
  		else
! 			error("%s:%s: %s\n", host, target, strerror(errno));
  		*tp = '\0';
  		return;
  	}
***************
*** 649,655 ****
  	struct timeval tvp[2];
  	char *owner, *group;
  	char new[BUFSIZ];
! 	extern char *tmpname;
  
  	cp = cmd;
  	opts = 0;
--- 665,671 ----
  	struct timeval tvp[2];
  	char *owner, *group;
  	char new[BUFSIZ];
! 	extern char *tempname;
  
  	cp = cmd;
  	opts = 0;
***************
*** 734,740 ****
  				ack();
  			return;
  		}
! 		error("%s:%s: %s\n", host, target, sys_errlist[errno]);
  		tp = stp[--catname];
  		*tp = '\0';
  		return;
--- 750,756 ----
  				ack();
  			return;
  		}
! 		error("%s:%s: %s\n", host, target, strerror(errno));
  		tp = stp[--catname];
  		*tp = '\0';
  		return;
***************
*** 744,755 ****
  		(void) sprintf(tp, "/%s", cp);
  	cp = rindex(target, '/');
  	if (cp == NULL)
! 		strcpy(new, tmpname);
  	else if (cp == target)
! 		(void) sprintf(new, "/%s", tmpname);
  	else {
  		*cp = '\0';
! 		(void) sprintf(new, "%s/%s", target, tmpname);
  		*cp = '/';
  	}
  
--- 760,771 ----
  		(void) sprintf(tp, "/%s", cp);
  	cp = rindex(target, '/');
  	if (cp == NULL)
! 		strcpy(new, tempname);
  	else if (cp == target)
! 		(void) sprintf(new, "/%s", tempname);
  	else {
  		*cp = '\0';
! 		(void) sprintf(new, "%s/%s", target, tempname);
  		*cp = '/';
  	}
  
***************
*** 829,835 ****
  		return;
  	}
  	if (wrerr) {
! 		error("%s:%s: %s\n", host, new, sys_errlist[olderrno]);
  		(void) unlink(new);
  		return;
  	}
--- 845,851 ----
  		return;
  	}
  	if (wrerr) {
! 		error("%s:%s: %s\n", host, new, strerror(olderrno));
  		(void) unlink(new);
  		return;
  	}
***************
*** 841,847 ****
  			goto badt;
  		if ((f2 = fopen(new, "r")) == NULL) {
  		badn:
! 			error("%s:%s: %s\n", host, new, sys_errlist[errno]);
  			(void) unlink(new);
  			return;
  		}
--- 857,863 ----
  			goto badt;
  		if ((f2 = fopen(new, "r")) == NULL) {
  		badn:
! 			error("%s:%s: %s\n", host, new, strerror(errno));
  			(void) unlink(new);
  			return;
  		}
***************
*** 873,879 ****
  	tvp[1].tv_sec = mtime;
  	tvp[1].tv_usec = 0;
  	if (utimes(new, tvp) < 0) {
! 		note("%s:utimes failed %s: %s\n", host, new, sys_errlist[errno]);
  	}
  	if (chog(new, owner, group, mode) < 0) {
  		(void) unlink(new);
--- 889,895 ----
  	tvp[1].tv_sec = mtime;
  	tvp[1].tv_usec = 0;
  	if (utimes(new, tvp) < 0) {
! 		note("%s:utimes failed %s: %s\n", host, new, strerror(errno));
  	}
  	if (chog(new, owner, group, mode) < 0) {
  		(void) unlink(new);
***************
*** 882,888 ****
  fixup:
  	if (rename(new, target) < 0) {
  badt:
! 		error("%s:%s: %s\n", host, target, sys_errlist[errno]);
  		(void) unlink(new);
  		return;
  	}
--- 898,904 ----
  fixup:
  	if (rename(new, target) < 0) {
  badt:
! 		error("%s:%s: %s\n", host, target, strerror(errno));
  		(void) unlink(new);
  		return;
  	}
***************
*** 935,946 ****
  	}
  	if (chkparent(target) < 0 ) {
  		error("%s:%s: %s (no parent)\n",
! 			host, target, sys_errlist[errno]);
  		return;
  	}
  	if (exists && (unlink(target) < 0)) {
  		error("%s:%s: %s (unlink)\n",
! 			host, target, sys_errlist[errno]);
  		return;
  	}
  	if (link(oldname, target) < 0) {
--- 951,962 ----
  	}
  	if (chkparent(target) < 0 ) {
  		error("%s:%s: %s (no parent)\n",
! 			host, target, strerror(errno));
  		return;
  	}
  	if (exists && (unlink(target) < 0)) {
  		error("%s:%s: %s (unlink)\n",
! 			host, target, strerror(errno));
  		return;
  	}
  	if (link(oldname, target) < 0) {
***************
*** 1037,1043 ****
  	if (chown(file, uid, gid) < 0 ||
  	    (mode & 06000) && chmod(file, mode) < 0) {
  		note("%s: chown or chmod failed: file %s:  %s",
! 			     host, file, sys_errlist[errno]);
  	}
  	if (userid)
  		setreuid(0, userid);
--- 1053,1059 ----
  	if (chown(file, uid, gid) < 0 ||
  	    (mode & 06000) && chmod(file, mode) < 0) {
  		note("%s: chown or chmod failed: file %s:  %s",
! 			     host, file, strerror(errno));
  	}
  	if (userid)
  		setreuid(0, userid);
***************
*** 1146,1152 ****
  		return;
  	}
  	if ((d = opendir(target)) == NULL) {
! 		error("%s:%s: %s\n", host, target, sys_errlist[errno]);
  		return;
  	}
  	ack();
--- 1162,1168 ----
  		return;
  	}
  	if ((d = opendir(target)) == NULL) {
! 		error("%s:%s: %s\n", host, target, strerror(errno));
  		return;
  	}
  	ack();
***************
*** 1156,1162 ****
  	while (dp = readdir(d)) {
  		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
  			continue;
! 		if (len + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
  			error("%s:%s/%s: Name too long\n",
  				host, target, dp->d_name);
  			continue;
--- 1172,1178 ----
  	while (dp = readdir(d)) {
  		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
  			continue;
! 		if (len + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) {
  			error("%s:%s/%s: Name too long\n",
  				host, target, dp->d_name);
  			continue;
***************
*** 1168,1174 ****
  			;
  		tp--;
  		if (lstat(target, &stb) < 0) {
! 			error("%s:%s: %s\n", host, target, sys_errlist[errno]);
  			continue;
  		}
  		(void) sprintf(buf, "Q%s\n", dp->d_name);
--- 1184,1190 ----
  			;
  		tp--;
  		if (lstat(target, &stb) < 0) {
! 			error("%s:%s: %s\n", host, target, strerror(errno));
  			continue;
  		}
  		(void) sprintf(buf, "Q%s\n", dp->d_name);
***************
*** 1234,1240 ****
  	while (dp = readdir(d)) {
  		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
  			continue;
! 		if (len + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
  			error("%s:%s/%s: Name too long\n",
  				host, target, dp->d_name);
  			continue;
--- 1250,1256 ----
  	while (dp = readdir(d)) {
  		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
  			continue;
! 		if (len + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) {
  			error("%s:%s/%s: Name too long\n",
  				host, target, dp->d_name);
  			continue;
***************
*** 1246,1252 ****
  			;
  		tp--;
  		if (lstat(target, &stb) < 0) {
! 			error("%s:%s: %s\n", host, target, sys_errlist[errno]);
  			continue;
  		}
  		remove(&stb);
--- 1262,1268 ----
  			;
  		tp--;
  		if (lstat(target, &stb) < 0) {
! 			error("%s:%s: %s\n", host, target, strerror(errno));
  			continue;
  		}
  		remove(&stb);
***************
*** 1256,1262 ****
  	*tp = '\0';
  	if (rmdir(target) < 0) {
  bad:
! 		error("%s:%s: %s\n", host, target, sys_errlist[errno]);
  		return;
  	}
  removed:
--- 1272,1278 ----
  	*tp = '\0';
  	if (rmdir(target) < 0) {
  bad:
! 		error("%s:%s: %s\n", host, target, strerror(errno));
  		return;
  	}
  removed:
***************
*** 1278,1284 ****
  	extern int userid, groupid;
  
  	if (pipe(fd) < 0) {
! 		error("%s\n", sys_errlist[errno]);
  		return;
  	}
  	if ((pid = fork()) == 0) {
--- 1294,1300 ----
  	extern int userid, groupid;
  
  	if (pipe(fd) < 0) {
! 		error("%s\n", strerror(errno));
  		return;
  	}
  	if ((pid = fork()) == 0) {
***************
*** 1336,1416 ****
  		ack();
  }
  
  /*VARARGS2*/
! log(fp, fmt, a1, a2, a3)
  	FILE *fp;
  	char *fmt;
! 	int a1, a2, a3;
  {
  	/* Print changes locally if not quiet mode */
  	if (!qflag)
! 		printf(fmt, a1, a2, a3);
  
  	/* Save changes (for mailing) if really updating files */
  	if (!(options & VERIFY) && fp != NULL)
! 		fprintf(fp, fmt, a1, a2, a3);
  }
  
  /*VARARGS1*/
! error(fmt, a1, a2, a3)
  	char *fmt;
! 	int a1, a2, a3;
  {
  	static FILE *fp;
  
  	++nerrs;
  	if (!fp && !(fp = fdopen(rem, "w")))
  		return;
  	if (iamremote) {
  		(void)fprintf(fp, "%crdist: ", 0x01);
! 		(void)fprintf(fp, fmt, a1, a2, a3);
  		fflush(fp);
  	}
  	else {
  		fflush(stdout);
  		(void)fprintf(stderr, "rdist: ");
! 		(void)fprintf(stderr, fmt, a1, a2, a3);
  		fflush(stderr);
  	}
  	if (lfp != NULL) {
  		(void)fprintf(lfp, "rdist: ");
! 		(void)fprintf(lfp, fmt, a1, a2, a3);
  		fflush(lfp);
  	}
  }
  
  /*VARARGS1*/
! fatal(fmt, a1, a2,a3)
  	char *fmt;
! 	int a1, a2, a3;
  {
  	static FILE *fp;
  
  	++nerrs;
  	if (!fp && !(fp = fdopen(rem, "w")))
  		return;
  	if (iamremote) {
  		(void)fprintf(fp, "%crdist: ", 0x02);
! 		(void)fprintf(fp, fmt, a1, a2, a3);
  		fflush(fp);
  	}
  	else {
  		fflush(stdout);
  		(void)fprintf(stderr, "rdist: ");
! 		(void)fprintf(stderr, fmt, a1, a2, a3);
  		fflush(stderr);
  	}
  	if (lfp != NULL) {
  		(void)fprintf(lfp, "rdist: ");
! 		(void)fprintf(lfp, fmt, a1, a2, a3);
  		fflush(lfp);
  	}
  	cleanup();
  }
  
  response()
  {
! 	char *cp, *s;
  	char resp[BUFSIZ];
  
  	if (debug)
--- 1352,1444 ----
  		ack();
  }
  
+ #include <varargs.h>
+ 
  /*VARARGS2*/
! log(fp, fmt, va_alist)
  	FILE *fp;
  	char *fmt;
! 	va_dcl
  {
+ 	va_list ap;
+ 
+ 	va_start(ap);
  	/* Print changes locally if not quiet mode */
  	if (!qflag)
! 		vprintf(fmt, ap);
  
  	/* Save changes (for mailing) if really updating files */
  	if (!(options & VERIFY) && fp != NULL)
! 		(void)vfprintf(fp, fmt, ap);
! 	va_end(ap);
  }
  
  /*VARARGS1*/
! error(fmt, va_alist)
  	char *fmt;
! 	va_dcl
  {
  	static FILE *fp;
+ 	va_list ap;
  
+ 	va_start(ap);
  	++nerrs;
  	if (!fp && !(fp = fdopen(rem, "w")))
  		return;
  	if (iamremote) {
  		(void)fprintf(fp, "%crdist: ", 0x01);
! 		(void)vfprintf(fp, fmt, ap);
  		fflush(fp);
  	}
  	else {
  		fflush(stdout);
  		(void)fprintf(stderr, "rdist: ");
! 		(void)vfprintf(stderr, fmt, ap);
  		fflush(stderr);
  	}
  	if (lfp != NULL) {
  		(void)fprintf(lfp, "rdist: ");
! 		(void)vfprintf(lfp, fmt, ap);
  		fflush(lfp);
  	}
+ 	va_end(ap);
  }
  
  /*VARARGS1*/
! fatal(fmt, va_alist)
  	char *fmt;
! 	va_dcl
  {
  	static FILE *fp;
+ 	va_list ap;
  
+ 	va_start(ap);
  	++nerrs;
  	if (!fp && !(fp = fdopen(rem, "w")))
  		return;
  	if (iamremote) {
  		(void)fprintf(fp, "%crdist: ", 0x02);
! 		(void)vfprintf(fp, fmt, ap);
  		fflush(fp);
  	}
  	else {
  		fflush(stdout);
  		(void)fprintf(stderr, "rdist: ");
! 		(void)vfprintf(stderr, fmt, ap);
  		fflush(stderr);
  	}
  	if (lfp != NULL) {
  		(void)fprintf(lfp, "rdist: ");
! 		(void)vfprintf(lfp, fmt, ap);
  		fflush(lfp);
  	}
  	cleanup();
+ 	va_end(ap);
  }
  
  response()
  {
! 	register char *cp, *s;
  	char resp[BUFSIZ];
  
  	if (debug)
***************
*** 1460,1480 ****
   */
  cleanup()
  {
! 	(void) unlink(tmpfile);
  	exit(1);
  }
  
! note(fmt, a1, a2, a3)
  {
! 	static char buf[BUFSIZ];
! 	sprintf(buf, fmt, a1, a2, a3);
  	comment(buf);
  }
  
  comment(s)
! char *s;
  {
  	char c = '\3';
  	write(rem, &c, 1);
  	write(rem, s, strlen(s));
  	c = '\n';
--- 1488,1515 ----
   */
  cleanup()
  {
! 	(void) unlink(tempfile);
  	exit(1);
  }
  
! note(fmt, va_alist)
! 	char *fmt;
! 	va_dcl
  {
! 	char buf[BUFSIZ];
! 	va_list ap;
! 
! 	va_start(ap);
! 	(void)vsprintf(buf, fmt, ap);
! 	va_end(ap);
  	comment(buf);
  }
  
  comment(s)
! 	char *s;
  {
  	char c = '\3';
+ 
  	write(rem, &c, 1);
  	write(rem, s, strlen(s));
  	c = '\n';
*** /VERSION.old	Fri May 12 20:45:36 1995
--- /VERSION	Sat May 13 21:37:09 1995
***************
*** 1,4 ****
! Current Patch Level: 242
  
  2.11 BSD
  ============
--- 1,4 ----
! Current Patch Level: 243
  
  2.11 BSD
  ============
