Commit 6b1fea2b authored by Michael Stapelberg's avatar Michael Stapelberg

Import Upstream version 0.53

parents
#
# Copyright (c) 2006, 2007, 2008 Niall O'Higgins <niallo@p2presearch.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# $Id: BSDmakefile,v 1.11 2008-10-05 23:56:25 niallo Exp $
CC?= cc
CFLAGS+= -Wall
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+= -Wmissing-declarations
CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
CFLAGS+= -Wsign-compare -g -ggdb
# Uncomment when building shared library
#CFLAGS+= -fPIC
LDFLAGS+= -L.
#
# Uncomment if you like to use Boehm's garbage collector (/usr/ports/devel/boehm-gc).
#LDFLAGS+= -L/usr/local/lib -lgc -lpthread
#DPADD+= /usr/local/lib/libgc.a
#CFLAGS+= -DUSE_BOEHM_GC -DGC_DEBUG -DFIND_LEAK -I/usr/local/include/gc
# You can also use Boehm's garbage collector as a means to find leaks.
# # export GC_FIND_LEAK=1
PROG= unworkable
SRCS= announce.c bencode.c buf.c ctl_server.c network.c parse.y progressmeter.c scheduler.c torrent.c trace.c util.c xmalloc.c
OBJS= ${SRCS:N*.h:N*.sh:R:S/$/.o/g}
MAN= unworkable.1
all: ${PROG} unworkable.cat1
${PROG}: libunworkable.a main.o
${CC} -o ${.TARGET} ${LDFLAGS} -levent -lcrypto main.o -lunworkable
libunworkable.a: ${OBJS}
ar rcs libunworkable.a ${OBJS}
# shared library not built by default, but it can be produced.
libunworkable.so.1: ${OBJS}
gcc -shared -Wl,-soname,libunworkable.so.1 \
-o libunworkable.so.0.5.1 $(OBJS)
unworkable.cat1: ${MAN}
nroff -Tascii -mandoc $(MAN) > unworkable.cat1
clean:
rm -rf *.o *.a *.so.1 openbsd-compat/*.o ${PROG} y.tab.h unworkable.cat1
#
# Copyright (c) 2008 Michael Stapelberg <michael+unworkable@stapelberg.de>
# Copyright (c) 2006 Niall O'Higgins <niallo@unworkable.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
CC?= cc
CFLAGS+= -Wall
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+= -Wmissing-declarations
CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
CFLAGS+= -Wsign-compare -g -ggdb
CFLAGS+= -Iopenbsd-compat
PROG=unworkable
SRCS=announce.c bencode.c buf.c ctl_server.c main.c network.c \
parse.y progressmeter.c scheduler.c torrent.c trace.c util.c xmalloc.c
LIBS=-levent -lcrypto -lpthread
UNAME=$(shell uname)
ifneq (, $(filter Linux GNU GNU/%, $(UNAME)))
SRCS+=openbsd-compat/strlcpy.c
SRCS+=openbsd-compat/strlcat.c
SRCS+=openbsd-compat/sha1.c
SRCS+=openbsd-compat/strtonum.c
CFLAGS+=-DNO_STRLCPY
CFLAGS+=-DNO_STRLCAT
CFLAGS+=-DNO_STRTONUM
else
ifeq ($(UNAME),sunos)
SRCS+=openbsd-compat/err.c
SRCS+=openbsd-compat/errx.c
SRCS+=openbsd-compat/warn.c
SRCS+=openbsd-compat/warnx.c
SRCS+=openbsd-compat/verr.c
SRCS+=openbsd-compat/verrx.c
SRCS+=openbsd-compat/vwarnx.c
SRCS+=openbsd-compat/vwarn.c
CFLAGS+=-DNO_ERR
CFLAGS+=-I/usr/local/ssl/include
LIBS+=-L/usr/local/ssl/lib
LIBS+=-L/usr/ucblib
LIBS+=-lsocket
LIBS+=-lnsl
LIBS+=-lucb
else
ifeq ($(UNAME),Darwin)
LIBS+=-L/opt/local/lib
CFLAGS+=-I/opt/local/include
endif
endif
endif
OBJS=$(patsubst %.y,%.o,$(patsubst %.c,%.o,${SRCS}))
MAN=unworkable.1
all: ${PROG}
${PROG}: ${OBJS}
${CC} -o $@ ${LDFLAGS} ${OBJS} ${LIBS}
clean:
rm -rf *.o openbsd-compat/*.o *.so ${PROG} y.tab.h
distclean: clean
rm -rf unworkable
libunworkable.so:
CFLAGS=-fPIC make unworkable
${CC} -o $@ ${LDFLAGS} -shared ${OBJS} ${LIBS}
install:
install -m 755 -d $(DESTDIR)/usr/bin
install -m 755 -d $(DESTDIR)/usr/share/man/man1
install -m 755 ${PROG} $(DESTDIR)/usr/bin
install -m 644 ${MAN} $(DESTDIR)/usr/share/man/man1
install-library:
install -m 755 -d /usr/local/lib
install -m 755 -d /usr/local/include/unworkable/sys
install -m 755 libunworkable.so /usr/local/lib
install -m 644 unworkable.h /usr/local/include/unworkable
install -m 644 openbsd-compat/sys/tree.h /usr/local/include/unworkable/sys
install -m 644 unworkable.pc /usr/local/lib/pkgconfig/unworkable.pc
Unworkable BitTorrent Implementation
Author: Niall O'Higgins <niallo at p2presearch.com>
Homepage: http://p2presearch.com/unworkable/
====================================================
Unworkable is a BSD-licensed BitTorrent implementation for UNIX written
from-scratch in C. It uses libevent for scalable asynchronous networking and
the mmap() system call for local data access. Some of the goals of the project
include (in no particular order) high code quality, efficiency, simplicity and
security.
FEATURES
========
Unworkable is still in an early stage of development, and is far behind most
other BitTorrent implementations. However, it is usable for some basic things
and the source code is quite minimal (4,000 lines of C compared to rTorrent's
40,000+ of C++).
Current state:
Unworkable currently lacks support for the following:
* HTTP/1.1 client. Many trackers do not correctly support HTTP/1.0 so
downloads will not work.
* Encryption.
* Trackerless (DHT) operation.
* Probably lots of other stuff.
BUILDING
========
Unworkable will build cleanly on OpenBSD (tested on i386, amd64, zaurus,
sparc64, macppc) without any additional dependencies beyond the base install.
Simply type 'make'.
On other platforms, you must use the SCons (http://www.scons.org) build tool.
After installing scons, type 'scons' to compile. Make sure you have libevent
and OpenSSL installed. If you get it working on other platforms, please let me
know and send along any portability diffs. It is known to work on at least
FreeBSD 6.2, Ubuntu Linux 8.04, Centos 5, Fedora 7 (on EC 2), Gentoo Linux,
Arch Linux, Mandriva Linux 2008.1. Mac OS X, Solaris 10 and Windows XP (cygwin).
# scons (http://www.scons.org) build for non-OpenBSD systems
# on OpenBSD, just type 'make'.
# $Id: SConstruct,v 1.17 2008-09-09 05:42:13 niallo Exp $
import sys
SRCS = ['announce.c', 'bencode.c', 'buf.c', 'ctl_server.c', 'main.c', 'network.c', 'parse.y', 'progressmeter.c', \
'scheduler.c', 'torrent.c', 'trace.c', 'util.c', 'xmalloc.c']
LIBS = ['event', 'crypto']
LIBPATH = ['/usr/lib', '/usr/local/lib']
CPPPATH = ['/usr/include', '/usr/local/include']
CCFLAGS = ['-Wall', '-Wstrict-prototypes', '-Wmissing-prototypes', '-Wmissing-declarations', '-Wshadow', '-Wpointer-arith', '-Wcast-qual', '-Wsign-compare', '-g', '-ggdb']
# Assume this is Solaris with packages from www.sunfreeware.com
if sys.platform.startswith('sunos'):
SRCS.append('openbsd-compat/err.c')
SRCS.append('openbsd-compat/errx.c')
SRCS.append('openbsd-compat/warn.c')
SRCS.append('openbsd-compat/warnx.c')
SRCS.append('openbsd-compat/verr.c')
SRCS.append('openbsd-compat/verrx.c')
SRCS.append('openbsd-compat/vwarnx.c')
SRCS.append('openbsd-compat/vwarn.c')
CPPPATH.append('/usr/local/ssl/include')
CPPPATH.append('openbsd-compat/')
LIBPATH.append('/usr/local/ssl/lib')
LIBPATH.append('/usr/ucblib')
LIBS.append('socket')
LIBS.append('nsl')
LIBS.append('ucb')
CCFLAGS.append('-DNO_ERR')
# Assume this is Mac OS X with macports, so stuff is under /opt
elif sys.platform.startswith('darwin'):
LIBPATH.append('/opt/local/lib')
CPPPATH.append('/opt/local/include')
# Explicitly make off_t 64bit on Linux
elif sys.platform.startswith('linux'):
CCFLAGS.append('-D_FILE_OFFSET_BITS=64')
env = Environment(LIBPATH=LIBPATH, CPPPATH=CPPPATH)
conf = Configure(env)
if not conf.CheckType('u_int8_t', '#include <sys/types.h>\n'):
CCFLAGS.append('-Du_int8_t=unsigned char')
if not conf.CheckType('u_int32_t', '#include <sys/types.h>\n'):
CCFLAGS.append('-Du_int32_t=unsigned int')
if not conf.CheckType('u_int64_t', '#include <sys/types.h>\n'):
CCFLAGS.append('-Du_int64_t=unsigned long long')
if not conf.CheckType('int64_t', '#include <sys/types.h>\n'):
CCFLAGS.append('-Dint64_t=long long')
if not conf.CheckCHeader('openssl/bn.h'):
print "No openssl/bn.h found. Do you have the OpenSSL headers correctly installed?"
Exit(1)
if not conf.CheckCHeader('openssl/dh.h'):
print "No openssl/dh.h found. Do you have the OpenSSL headers correctly installed?"
Exit(1)
if not conf.CheckCHeader('openssl/engine.h'):
print "No openssl/engine.h found. Do you have the OpenSSL headers correctly installed?"
Exit(1)
if not conf.CheckCHeader('sys/queue.h') or not conf.CheckCHeader('sys/tree.h') \
or not conf.CheckCHeader('sha1.h'):
print "Missing some headers, using bundled includes"
CPPPATH.append('openbsd-compat/')
if not conf.CheckFunc('strlcpy'):
print "No system strlcpy found. Using bundled version"
SRCS.append('openbsd-compat/strlcpy.c')
conf.env.Append(CCFLAGS = '-DNO_STRLCPY')
CCFLAGS.append('-DNO_STRLCPY')
if not conf.CheckFunc('strlcat'):
print "No system strlcat found. Using bundled version"
SRCS.append('openbsd-compat/strlcat.c')
CCFLAGS.append('-DNO_STRLCAT')
if not conf.CheckFunc('strtonum'):
print "No system strtonum found. Using bundled version"
SRCS.append('openbsd-compat/strtonum.c')
CCFLAGS.append('-DNO_STRTONUM')
if not conf.CheckFunc('SHA1Update'):
print "No system SHA1Update found. Using bundled version"
SRCS.append('openbsd-compat/sha1.c')
if not conf.CheckFunc('getaddrinfo') and not sys.platform.startswith('sunos'):
print "No system getaddrinfo() found. Using bundled version"
SRCS.append('openbsd-compat/getaddrinfo.c')
CCFLAGS.append('-DNO_GETADDRINFO')
if not conf.CheckLib('crypto'):
print "OpenSSL crypto library not found on your system. You can get it at http://www.openssl.org"
Exit(1)
if not conf.CheckLib('event'):
print "Libevent not found on your system. You can get it at http://monkey.org/~provos/libevent/"
Exit(1)
env = conf.Finish()
env.Program('unworkable', SRCS, LIBS=LIBS, LIBPATH=LIBPATH, CPPPATH=CPPPATH, CCFLAGS=CCFLAGS)
- Better progress guage handling of the situation where we have received
more bytes than are in the torrent, but hash check failures mean
we aren't actually as far along as we wish. In other words, raw data
rx vs. checksummed pieces.
- UDP tracker support (BEP 15).
- Multi-tracker support.
- Multiple torrents per unworkable process support, along with hooks
to load new torrents etc in the control server.
- Encryption.
- DHT/Kadamalia overlay network support.
- Rate limiting.
This diff is collapsed.
/* $Id: bencode.c,v 1.41 2008-10-21 19:01:15 niallo Exp $ */
/*
* Copyright (c) 2006, 2007, 2008 Niall O'Higgins <niallo@p2presearch.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "includes.h"
#define IS_CONTAINER_TYPE(x) \
(x->flags & BDICT || x->flags & BLIST)
struct benc_node *root;
/*
* benc_node_add()
*
* Add new node to tail of node's child queue.
*/
void
benc_node_add(struct benc_node *node, struct benc_node *new)
{
TAILQ_INSERT_TAIL(&node->children, new, benc_nodes);
}
/*
* benc_node_add_head()
*
* Add new node to head of node's child queue
*/
void
benc_node_add_head(struct benc_node *node, struct benc_node *new)
{
TAILQ_INSERT_HEAD(&node->children, new, benc_nodes);
}
/*
* benc_node_create()
*
* Create and initialise a benc_node
*/
struct benc_node *
benc_node_create(void)
{
struct benc_node *node;
node = xmalloc(sizeof(*node));
memset(node, 0, sizeof(*node));
TAILQ_INIT(&(node->children));
return (node);
}
/*
* benc_node_find()
*
* Find BDICT_ENTRY node with specified key.
*/
struct benc_node *
benc_node_find(struct benc_node *node, char *key)
{
struct benc_node *childnode, *ret;
if (node->flags & BDICT_ENTRY
&& strcmp(key, node->body.dict_entry.key) == 0)
return (node->body.dict_entry.value);
if (node->flags & BDICT_ENTRY
&& IS_CONTAINER_TYPE(node))
TAILQ_FOREACH(childnode,
&node->body.dict_entry.value->children, benc_nodes)
if ((ret = benc_node_find(childnode, key)) != NULL)
return (ret);
if (IS_CONTAINER_TYPE(node))
TAILQ_FOREACH(childnode, &node->children, benc_nodes)
if ((ret = benc_node_find(childnode, key)) != NULL)
return (ret);
return (NULL);
}
/*
* benc_node_print()
*
* Pretty-print a node tree.
*/
void
benc_node_print(struct benc_node *node, int level)
{
struct benc_node *childnode;
int i;
for (i = 0; i < level; i++)
printf("\t");
if (node->flags & BDICT_ENTRY) {
printf("key: %s", node->body.dict_entry.key);
benc_node_print(node->body.dict_entry.value, level);
} else if (node->flags & BSTRING) {
printf("string len: %zu value: %s\n", node->body.string.len,
node->body.string.value);
} else if (node->flags & BINT) {
printf("int value: %lld\n", node->body.number);
}
if (node->flags & BLIST) {
printf("blist\n");
TAILQ_FOREACH(childnode, &node->children, benc_nodes)
benc_node_print(childnode, level + 1);
}
if (node->flags & BDICT) {
printf("bdict, end: %zu\n", node->end);
TAILQ_FOREACH(childnode, &node->children, benc_nodes)
benc_node_print(childnode, level + 1);
}
}
/*
* benc_node_freeall()
*
* Walk the tree from this node down, freeing everything.
*/
void
benc_node_freeall(struct benc_node *node)
{
struct benc_node *childnode;
if (node->flags & BDICT_ENTRY) {
xfree(node->body.dict_entry.key);
benc_node_freeall(node->body.dict_entry.value);
} else if (node->flags & BSTRING) {
xfree(node->body.string.value);
}
if (IS_CONTAINER_TYPE(node)) {
while ((childnode = TAILQ_FIRST(&node->children)) != NULL) {
TAILQ_REMOVE(&node->children, childnode, benc_nodes);
benc_node_freeall(childnode);
}
}
if (node != NULL)
xfree(node);
}
/*
* benc_root_create()
*
* Create a root node, which parser needs to be passed during init
*/
struct benc_node *
benc_root_create(void)
{
struct benc_node *n = benc_node_create();
n->flags = BLIST;
return (n);
}
/* $Id: buf.c,v 1.11 2008-09-08 05:35:52 niallo Exp $ */
/*
* Copyright (c) 2003 Jean-Francois Brousseau <jfb@openbsd.org>
* Copyright (c) 2006, 2007, 2008 Niall O'Higgins <niallo@p2presearch.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "includes.h"
#define BUF_INCR 128
struct buf {
u_int cb_flags;
/* buffer handle and size */
u_char *cb_buf;
size_t cb_size;
/* start and length of valid data in buffer */
u_char *cb_cur;
size_t cb_len;
size_t cb_pos;
};
#define SIZE_LEFT(b) (b->cb_size - (size_t)(b->cb_cur - b->cb_buf) \
- b->cb_len)
static void buf_grow(BUF *, size_t);
/*
* buf_alloc()
*
* Create a new buffer structure and return a pointer to it. This structure
* uses dynamically-allocated memory and must be freed with buf_free(),
* once the buffer is no longer needed.
*/
BUF *
buf_alloc(size_t len, u_int flags)
{
BUF *b;
b = xmalloc(sizeof(*b));
/* Postpone creation of zero-sized buffers */
if (len > 0)
b->cb_buf = xcalloc(1, len);
else
b->cb_buf = NULL;
b->cb_flags = flags;
b->cb_size = len;
b->cb_cur = b->cb_buf;
b->cb_len = 0;
b->cb_pos = 0;
return (b);
}
/*
* buf_load()
*
* Open the file specified by <path> and load all of its contents into a
* buffer.
* Returns the loaded buffer on success.
*/
BUF *
buf_load(const char *path, u_int flags)
{
int fd;
ssize_t ret;
size_t len;
u_char *bp;
struct stat st;
BUF *buf;
if ((fd = open(path, O_RDONLY, 0600)) == -1) {
warn("%s", path);
return (NULL);
}
if (fstat(fd, &st) == -1)
err(1, "%s", path);
buf = buf_alloc((size_t)st.st_size, flags);
for (bp = buf->cb_cur; ; bp += (size_t)ret) {
len = SIZE_LEFT(buf);
ret = read(fd, bp, len);
if (ret == -1) {
buf_free(buf);
err(1, "buf_load");
} else if (ret == 0)
break;
buf->cb_len += (size_t)ret;
}
(void)close(fd);
return (buf);
}
/*
* buf_free()
*
* Free the buffer <b> and all associated data.
*/
void
buf_free(BUF *b)
{
if (b->cb_buf != NULL)
xfree(b->cb_buf);
xfree(b);
}
/*
* buf_release()
*
* Free the buffer <b>'s structural information but do not free the contents
* of the buffer. Instead, they are returned and should be freed later using
* xfree().
*/
void *
buf_release(BUF *b)
{
u_char *tmp;
tmp = b->cb_buf;
xfree(b);
return (tmp);
}
/*
* buf_set()
*
* Set the contents of the buffer <b> at offset <off> to the first <len>
* bytes of data found at <src>. If the buffer was not created with
* BUF_AUTOEXT, as many bytes as possible will be copied in the buffer.
*/
ssize_t
buf_set(BUF *b, const void *src, size_t len, size_t off)
{
size_t rlen = 0;
if (b->cb_size < (len + off)) {
if ((b->cb_flags & BUF_AUTOEXT)) {
buf_grow(b, len + off - b->cb_size);
rlen = len + off;
} else {
rlen = b->cb_size - off;
}
} else {
rlen = len;
}
b->cb_len = rlen;
memcpy((b->cb_buf + off), src, rlen);
if (b->cb_len == 0) {
b->cb_cur = b->cb_buf + off;
b->cb_len = rlen;
}
return (rlen);
}
/*
* buf_getc()
*
* Return u_char at buffer position <pos>.
*
*/
int
buf_getc(BUF *b)
{
int c;
if (b->cb_pos < b->cb_len) {
c = b->cb_cur[b->cb_pos];
b->cb_pos++;
return (c);
} else {
return (EOF);
}
}
void
buf_ungetc(BUF *b)
{
if (b->cb_len > 0)
b->cb_pos--;
}
/*
* buf_len()
*
* Returns the size of the buffer that is being used.
*/
size_t
buf_len(BUF *b)
{
return (b->cb_len);
}
/*
* buf_write_fd()
*
* Write the contents of the buffer <b> to the specified <fd>
*/
int
buf_write_fd(BUF *b, int fd)
{
u_char *bp;
size_t len;
ssize_t ret;
len = b->cb_len;
bp = b->cb_cur;
do {
ret = write(fd, bp, len);
if (ret == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
return (-1);
}