#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2.1).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2007-07-21 09:48 PDT by <lm@work>.
# Source directory was `/home/bk/lm/bkbits/src/client'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#    310 -r--r--r-- bk-client2.0/Makefile
#  10417 -r--r--r-- bk-client2.0/bkf.c
#    892 -r--r--r-- bk-client2.0/demo.sh
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
  shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
  shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
  shar_touch='touch -am $3$4$5$6$2 "$8"'
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
#
if mkdir _sh19828; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= bk-client2.0/Makefile ==============
if test ! -d 'bk-client2.0'; then
  $echo 'x -' 'creating directory' 'bk-client2.0'
  mkdir 'bk-client2.0'
fi
if test -f 'bk-client2.0/Makefile' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'bk-client2.0/Makefile' '(file already exists)'
else
  $echo 'x -' extracting 'bk-client2.0/Makefile' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'bk-client2.0/Makefile' &&
CFLAGS=-O2 -Wall -Wno-parentheses
X
all: bkf
X
clean clobber distclean:
X	rm -f bkf a.out *.o *.shar
X	rm -rf bk-client2.0
X	bk clean
X
demo: demo.sh bkf
X	sh demo.sh
X
shar: Makefile bkf.c demo.sh
X	rm -rf bk-client2.0
X	mkdir bk-client2.0
X	cp Makefile bkf.c demo.sh bk-client2.0
X	shar bk-client2.0 > bk-client2.0.shar
SHAR_EOF
  (set 20 07 07 21 09 48 33 'bk-client2.0/Makefile'; eval "$shar_touch") &&
  chmod 0444 'bk-client2.0/Makefile' ||
  $echo 'restore of' 'bk-client2.0/Makefile' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'bk-client2.0/Makefile:' 'MD5 check failed'
b9b7cb991264a6189a6030b5ad40b335  bk-client2.0/Makefile
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bk-client2.0/Makefile'`"
    test 310 -eq "$shar_count" ||
    $echo 'bk-client2.0/Makefile:' 'original size' '310,' 'current size' "$shar_count!"
  fi
fi
# ============= bk-client2.0/bkf.c ==============
if test -f 'bk-client2.0/bkf.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'bk-client2.0/bkf.c' '(file already exists)'
else
  $echo 'x -' extracting 'bk-client2.0/bkf.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'bk-client2.0/bkf.c' &&
/*
X * Copyright (c) 2005-2007 BitMover, Inc.
X *
X * Licensed under the GPL v2.
X *
X * Please send patches to dev@bitmover.com.
X */
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
X
#define	min(x, y)	((x) < (y) ? (x) : (y))
#define	unless(x)	if (!(x))
#define	streq(a, b)	!strcmp(a, b)
X
typedef	struct {
X	int	port;
X	char	host[500];
X	char	repo[1024];
} url;
X
int	changes(int ac, char **av);
int	chomp(char *s);
int	clone(int ac, char **av);
void	getline(int sock, char *buf, unsigned int len);
int	scanurl(url *u, char *p);
int	tcp_connect(char *host, int port);
int	parent(int ac, char **av);
int	pull(int ac, char **av);
int	help(int ac, char **av);
void	usage(void);
X
int
main(int ac, char **av)
{
X	unless (av[1]) {
X		exit(1);
X	}
X	if (streq(av[1], "changes")) return (changes(--ac, ++av));
X	if (streq(av[1], "clone")) return (clone(--ac, ++av));
X	if (streq(av[1], "pull")) return (pull(--ac, ++av));
X	if (streq(av[1], "parent")) return (parent(--ac, ++av));
X	if (streq(av[1], "help")) return (help(--ac, ++av));
X	if (streq(av[1], "--help")) return (help(--ac, ++av));
X	fprintf(stderr,
X	    "What an excellent idea!  You should implement 'bkf %s'\n"
X	    "Please send a patch to dev@bitmover.com.  Thanks!\n",
X	    av[1]);
X	return (1);
}
X
int
help(int ac, char **av)
{
X	puts(
"This is bkf - the 2nd generation free BitKeeper client for BKbits.net\n"
"\n"
"It supports the following commands:\n"
"\n"
"bkf clone [-q] [-r<rev>] <url>\n"
"	-q	be quiet\n"
"	-r<rev>	specifies rev to which to clone to, nothing after that comes\n"
"	<url>	specifies the repo, i.e., bk://mysql.bkbits.net/mysql-5.2\n"
"\n"
"bkf pull [-q] [<url>]\n"
"	-q	be quiet\n"
"	<url>	specifies the repo, i.e., bk://mysql.bkbits.net/mysql-5.2\n"
"	The default url is whatever you cloned from original\n"
"\n"
"bkf parent [<url>]\n"
"	Sets or shows the parent\n"
"\n"
"bkf changes\n"
"	This command talks to your parent to get repository history.\n"
"	With no options shows the history of your repository.\n"
"	-R	show any changesets in your parent that you don't have\n"
"	-r<rev>	show history for the specified revision\n"
"	-v	include file comments in output\n"
"	-vv	include file comments and diffs in output\n");
X	return (0);
}
X
/*
X * Get the tarball and unpack it.
X */
int
clone(int ac, char **av)
{
X	int	sock, i, bytes, c;
X	int	quiet = 0;
X	FILE	*f;
X	url	u;
X	char	*repo, *dst, *rev = "+";
X	char	buf[BUFSIZ];
X
X	while ((c = getopt(ac, av, "qr:")) != -1) {
X		switch (c) {
X		    case 'q': quiet = 1; break;
X		    case 'r': rev = optarg; break;
X		    default: 
usage:			fprintf(stderr,
X			    "usage: bkf clone [-r<rev>] "
X			    "bk://host[:port][/path_to_repo] dest\n");
X			exit(1);
X		}
X	}
X
X	unless ((ac - optind) == 2) goto usage;
X
X	repo = av[optind++];
X	dst = av[optind];
X
X	if (scanurl(&u, repo) != 0) {
X		fprintf(stderr, "Bad URL\n");
X		exit(1);
X	}
X
X	if (mkdir(dst, 0775)) {
X		perror(dst);
X		exit(1);
X	}
X	chdir(dst);
X	mkdir("BK", 0775);
X	f = fopen("BK/parent", "w");
X	fprintf(f, "%s\n", repo);
X	fclose(f);
X	unless ((sock = tcp_connect(u.host, u.port)) >= 0) {
X		perror(repo);
X		exit(1);
X	}
X	sprintf(buf, "putenv BK_VHOST=%s\n", u.host);
X	if (write(sock, buf, strlen(buf)) != strlen(buf)) exit(1);
X	if (u.repo[0]) {
X		unless (write(sock, "cd ", 3) == 3) exit(1);
X		unless (write(sock, u.repo, strlen(u.repo)) == strlen(u.repo)) {
X			exit(1);
X		}
X		unless (write(sock, "\n", 1) == 1) exit(1);
X	}
X	sprintf(buf, "bkf_tarball %s\n", rev);
X	unless (write(sock, buf, strlen(buf)) == strlen(buf)) exit(1);
line:	getline(sock, buf, sizeof(buf));
X	switch (buf[0]) {
X	    case 'I':
X		unless (quiet) fprintf(stderr, "%s", buf);
X		goto line;
X	    case 'E':
X		fprintf(stderr, "%s", buf);
X		exit(1);
X	    case 'O': goto line;	/* OK-root OK */
X	    case '@': break;		/* @BLOCK ... */
X	    default:
X	    	exit(1);
X	}
X	if (quiet) {
X		unless (f = popen("tar zxf -", "w")) exit(1);
X	} else {
X		unless (f = popen("tar zxvf -", "w")) exit(1);
X	}
X	while (sscanf(buf, "@BLOCK=%u@", &bytes) == 1) {
X		if (bytes == 0) {
X			pclose(f);
X			unless (quiet) printf("All done!\n");
X			exit(0);
X		}
X		do {
X			switch (i = read(sock, buf, min(bytes, sizeof(buf)))) {
X			    case 0: 
X			    case -1: perror("read"); break;
X			    default:
X				fwrite(buf, i, 1, f);
X				bytes -= i;
X				break;
X			}
X		} while (bytes > 0);
X		getline(sock, buf, sizeof(buf));
X	}
X	pclose(f);
X	exit(1);
}
X
int
parent(int ac, char **av)
{
X	FILE	*f;
X	char	buf[BUFSIZ];
X	url	u;
X
X	if (av[1]) {
X		if (scanurl(&u, av[1])) {
X			unless (f = fopen("BK/parent", "w")) {
X				perror("BK/parent");
X				exit(1);
X			}
X			fprintf(f, "%s\n", av[1]);
X			return (0);
X		} else {
X			fprintf(stderr, "Bad URL: %s\n", av[1]);
X			return (1);
X		}
X	}
X
X	if (f = fopen("BK/parent", "r")) {
X		fgets(buf, sizeof(buf), f);
X		printf("%s", buf);
X		fclose(f);
X	}
X	return (0);
}
X
/*
X * Get the patch and unpack it.
X */
int
pull(int ac, char **av)
{
X	int	sock, n, left, want, i;
X	int	quiet = 0;
X	FILE	*f;
X	char	buf[BUFSIZ];
X	url	u;
X
X	if (av[1] && streq(av[1], "-q")) {
X		quiet++;
X		ac--;
X		av++;
X	}
X	if (av[1] && scanurl(&u, av[1])) {
err:		fprintf(stderr,
X		    "usage: bkf pull [bk://host[:port][/path_to_repo]]\n");
X		exit(1);
X	}
X	unless (av[1]) {
X		if (f = fopen("BK/parent", "r")) {
X			fgets(buf, sizeof(buf), f);
X			chomp(buf);
X			fclose(f);
X			if (scanurl(&u, buf)) goto err;
X		} else {
X			goto err;
X		}
X	}
X	unless (f = fopen("BK/keys", "r")) exit(1);
X	while (fgets(buf, sizeof(buf), f)) {
X		chomp(buf);
X		if (putenv(strdup(buf))) perror(buf);
X	}
X	fclose(f);
X	unless (getenv("ROOTKEY")) {
X		fprintf(stderr, "No ROOTKEY in BK/keys\n");
X		exit(1);
X	}
X	unless (getenv("TIPKEY")) {
X		fprintf(stderr, "No TIPKEY BK/keys\n");
X		exit(1);
X	}
X	unless ((sock = tcp_connect(u.host, u.port)) >= 0) {
X		perror(av[1]);
X		exit(1);
X	}
X	sprintf(buf, "putenv BK_VHOST=%s\n", u.host);
X	if (write(sock, buf, strlen(buf)) != strlen(buf)) exit(1);
X	if (u.repo[0]) {
X		unless (write(sock, "cd ", 3) == 3) exit(1);
X		unless (write(sock, u.repo, strlen(u.repo)) == strlen(u.repo)) {
X			exit(1);
X		}
X		unless (write(sock, "\n", 1) == 1) exit(1);
X	}
X	sprintf(buf, "bkf_patch %s %s\n", getenv("ROOTKEY"), getenv("TIPKEY"));
X	unless (write(sock, buf, strlen(buf)) == strlen(buf)) exit(1);
line:	for (i = 0; ; i++) {
X		unless (read(sock, &buf[i], 1) == 1) exit(1);
X		if (buf[i] == '\n') {
X			buf[i+1] = 0;
X			break;
X		}
X	}
X	switch (buf[0]) {
X	    case 'I':
X		fprintf(stderr, "%s", buf);
X		if (streq("INFO-nothing to send.\n", buf)) exit(0);
X		goto line;
X	    case 'E':
X		fprintf(stderr, "%s", buf);
X		exit(1);
X	    case 'O':
X		/* Might be CD command OK line */
X		unless (sscanf(buf, "OK-patch coming, %u bytes", &left)== 1){
X			goto line;
X		}
X		fprintf(stderr, "%s", buf);
X		break;
X	    default:
X	    	exit(1);
X	}
X	want = min(sizeof(buf), left);
X	unless (want > 0) exit(0);
X	if (quiet) {
X		unless (f = popen("gunzip | patch -sp1 --binary", "w")) exit(1);
X	} else {
X		unless (f = popen("gunzip | patch -p1 --binary", "w")) exit(1);
X	}
X	unlink("BK/keys");
X	while ((n = read(sock, buf, want)) > 0) {
X		fwrite(buf, 1, n, f);
X		left -= n;
X		if (left <= 0) break;
X		want = min(sizeof(buf), left);
X	}
X	pclose(f);
X	while (read(sock, buf, 1) == 1) write(2, buf, 1);
X	return (0);
}
X
/*
X * XXX - we don't handle any quoting problems, simplistic interface.
X */
int
changes(int ac, char **av)
{
X	int	i, sock;
X	FILE	*f;
X	url	u;
X	char	buf[1024], buf2[1024];
X
X	if (f = fopen("BK/parent", "r")) {
X		fgets(buf, sizeof(buf), f);
X		chomp(buf);
X		fclose(f);
X		if (scanurl(&u, buf)) {
X			fprintf(stderr, "Bad URL %s\n", buf);
X			return (1);
X		}
X	} else {
X		fprintf(stderr, "bkf changes: set a parent first.\n");
X		return (1);
X	}
X	unless (f = fopen("BK/keys", "r")) exit(1);
X	while (fgets(buf2, sizeof(buf2), f)) {
X		chomp(buf2);
X		if (putenv(strdup(buf2))) perror(buf2);
X	}
X	fclose(f);
X	unless ((sock = tcp_connect(u.host, u.port)) >= 0) {
X		perror(av[1]);
X		exit(1);
X	}
X	sprintf(buf, "putenv BK_VHOST=%s\n", u.host);
X	if (write(sock, buf, strlen(buf)) != strlen(buf)) exit(1);
X	if (u.repo[0]) {
X		unless (write(sock, "cd ", 3) == 3) exit(1);
X		unless (write(sock, u.repo, strlen(u.repo)) == strlen(u.repo)) {
X			exit(1);
X		}
X		unless (write(sock, "\n", 1) == 1) exit(1);
X	}
X	strcpy(buf, "bkf_changes");
X	if (av[1] && streq(av[1], "-R")) {
X		sprintf(buf2, "-r%s..", getenv("TIPKEY"));
X		strcat(buf, " ");
X		strcat(buf, buf2);
X	} else unless (av[1]) {
X		sprintf(buf2, "-r..%s", getenv("TIPKEY"));
X		strcat(buf, " ");
X		strcat(buf, buf2);
X	} else {
X		for (i = 1; av[i]; ++i) {
X			strcat(buf, " ");
X			strcat(buf, av[i]);
X		}
X	}
X	strcat(buf, "\n");
X	if (write(sock, buf, strlen(buf)) != strlen(buf)) exit(1);
X	while ((i = read(sock, buf, sizeof(buf))) > 0) {
X		write(1, buf, i);
X	}
X	return (0);
}
X
/*
X * Connect to the TCP socket advertised as "port" on "host" and
X * return the connected socket.
X */
int
tcp_connect(char *host, int port)
{
X	struct	hostent *h;
X	struct	sockaddr_in s;
X	int	sock;
X
X	if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
X		perror("socket");
X		return (-1);
X	}
X	unless (h = gethostbyname(host)) return (-2);
X	memset((void *) &s, 0, sizeof(s));
X	s.sin_family = AF_INET;
X	memmove((void *)&s.sin_addr, (void*)h->h_addr, h->h_length);
X	s.sin_port = htons(port);
X	if (connect(sock, (struct sockaddr*)&s, sizeof(s)) < 0) {
X		return (-3);
X	}
X	return (sock);
}
X
int
scanurl(url *u, char *p)
{
X	char	*t;
X	char	buf[1024];
X
X	strcpy(buf, p);
X	p = buf;
X	if (strncmp("bk://", p, 5)) return (1);
X	u->repo[0] = 0;
X	p += 5;
X	unless (*p) return (1);
X
X	/* bk://hostname:port[/path] */
X	if (t = strchr(p, ':')) {
X		*t++ = 0;
X		strcpy(u->host, p);
X		u->port = atoi(t);
X		for (p = t; isdigit(*p); p++);
X		if (*p == '/') strcpy(u->repo, p+1);
X		t[-1] = ':';
X		return (0);
X	}
X	u->port = 0x3962;
X	if (t = strchr(p, '/')) {
X		*t++ = 0;
X		strcpy(u->host, p);
X		strcpy(u->repo, t);
X		t[-1] = '/';
X		return (0);
X    	}
X	strcpy(u->host, p);
X	return (0);
}
X
void
getline(int sock, char *buf, unsigned int len)
{
X	unsigned int i;
X
X	for (i = 0; i < len - 1; i++) {
X		unless (read(sock, &buf[i], 1) == 1) exit(1);
X		if (buf[i] == '\n') {
X			buf[i+1] = 0;
X			break;
X		}
X	}
X    	buf[i+1] = 0;
}
X
int     
chomp(char *s)  
{       
X	int     any = 0;
X	char    *p;
X
X	p = s + strlen(s); 
X	while ((p > s) && ((p[-1] == '\n') || (p[-1] == '\r'))) --p, any = 1;
X	*p = 0; 
X	return (any);
}       
SHAR_EOF
  (set 20 07 07 21 09 48 33 'bk-client2.0/bkf.c'; eval "$shar_touch") &&
  chmod 0444 'bk-client2.0/bkf.c' ||
  $echo 'restore of' 'bk-client2.0/bkf.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'bk-client2.0/bkf.c:' 'MD5 check failed'
99ed1426ee08e4a9856ca9a6b0fa23b1  bk-client2.0/bkf.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bk-client2.0/bkf.c'`"
    test 10417 -eq "$shar_count" ||
    $echo 'bk-client2.0/bkf.c:' 'original size' '10417,' 'current size' "$shar_count!"
  fi
fi
# ============= bk-client2.0/demo.sh ==============
if test -f 'bk-client2.0/demo.sh' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'bk-client2.0/demo.sh' '(file already exists)'
else
  $echo 'x -' extracting 'bk-client2.0/demo.sh' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'bk-client2.0/demo.sh' &&
#!/bin/sh
X
PATH=$PWD:$PATH
test -d sandbox && /bin/rm -rf sandbox
test -x bkf || {
X	echo bkf needs to be in your PATH
X	exit 1
}
echo =========================================================================
echo -n 'Press return to get the audiofile repo as of cset 1.100 '
read x
bkf clone -r1.100 bk://audiofile.bkbits.net/audiofile/ sandbox
echo =========================================================================
echo -n 'Press return to see what is available for update '
read x
( cd sandbox && bkf changes -R )
echo =========================================================================
echo -n 'Press return to update to the the most recent audiofile repo '
read x
( cd sandbox && bkf pull )
echo =========================================================================
echo Data is in ./sandbox
echo =========================================================================
SHAR_EOF
  (set 20 07 07 21 09 48 33 'bk-client2.0/demo.sh'; eval "$shar_touch") &&
  chmod 0444 'bk-client2.0/demo.sh' ||
  $echo 'restore of' 'bk-client2.0/demo.sh' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'bk-client2.0/demo.sh:' 'MD5 check failed'
1f27adde57dfb6006ccdf889d8c06f67  bk-client2.0/demo.sh
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bk-client2.0/demo.sh'`"
    test 892 -eq "$shar_count" ||
    $echo 'bk-client2.0/demo.sh:' 'original size' '892,' 'current size' "$shar_count!"
  fi
fi
rm -fr _sh19828
exit 0
