LibSAM
This commit is contained in:
27
apps/sam/c/LICENSE
Normal file
27
apps/sam/c/LICENSE
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.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:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the author nor the names of any contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
65
apps/sam/c/Makefile.cygwin
Normal file
65
apps/sam/c/Makefile.cygwin
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#
|
||||||
|
# This Makefile is compatible with GNU Make and should work on Cygwin
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Your operating system
|
||||||
|
#
|
||||||
|
|
||||||
|
OS = CYGWIN
|
||||||
|
|
||||||
|
#
|
||||||
|
# Directories
|
||||||
|
#
|
||||||
|
|
||||||
|
INCDIR = inc
|
||||||
|
LIBDIR = lib
|
||||||
|
OBJDIR = obj
|
||||||
|
SRCDIR = src
|
||||||
|
|
||||||
|
#
|
||||||
|
# Programs
|
||||||
|
#
|
||||||
|
|
||||||
|
AR = ar
|
||||||
|
CC = gcc
|
||||||
|
|
||||||
|
#
|
||||||
|
# Flags
|
||||||
|
#
|
||||||
|
|
||||||
|
CFLAGS = -g -march=i486 -O2 -pipe -std=c99 -Wall
|
||||||
|
CFLAGS += -DOS=$(OS)
|
||||||
|
CFLAGS += -I$(INCDIR)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Object files
|
||||||
|
#
|
||||||
|
|
||||||
|
OBJS = $(OBJDIR)/sam.o \
|
||||||
|
$(OBJDIR)/snprintf.o \
|
||||||
|
$(OBJDIR)/strl.o
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build rules
|
||||||
|
#
|
||||||
|
|
||||||
|
all: depend libsam
|
||||||
|
|
||||||
|
depend:
|
||||||
|
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
libsam: $(OBJS)
|
||||||
|
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Cleanup rules
|
||||||
|
#
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
|
||||||
|
|
||||||
|
tidy: clean
|
65
apps/sam/c/Makefile.debian
Normal file
65
apps/sam/c/Makefile.debian
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#
|
||||||
|
# This Makefile is compatible with GNU Make and should work on Linux
|
||||||
|
# (Tested on Debian 3.0)
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Your operating system
|
||||||
|
#
|
||||||
|
|
||||||
|
OS = LINUX
|
||||||
|
|
||||||
|
#
|
||||||
|
# Directories
|
||||||
|
#
|
||||||
|
|
||||||
|
INCDIR = inc
|
||||||
|
LIBDIR = lib
|
||||||
|
OBJDIR = obj
|
||||||
|
SRCDIR = src
|
||||||
|
|
||||||
|
#
|
||||||
|
# Programs
|
||||||
|
#
|
||||||
|
|
||||||
|
AR = ar
|
||||||
|
CC = gcc-3.0
|
||||||
|
|
||||||
|
#
|
||||||
|
# Flags
|
||||||
|
#
|
||||||
|
|
||||||
|
CFLAGS = -g -march=i486 -O2 -pipe -std=c99 -Wall
|
||||||
|
CFLAGS += -DOS=$(OS)
|
||||||
|
CFLAGS += -I$(INCDIR)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Object files
|
||||||
|
#
|
||||||
|
|
||||||
|
OBJS = $(OBJDIR)/sam.o \
|
||||||
|
$(OBJDIR)/strl.o
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build rules
|
||||||
|
#
|
||||||
|
|
||||||
|
all: depend libsam
|
||||||
|
|
||||||
|
depend:
|
||||||
|
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
libsam: $(OBJS)
|
||||||
|
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Cleanup rules
|
||||||
|
#
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
|
||||||
|
|
||||||
|
tidy: clean
|
64
apps/sam/c/Makefile.linux
Normal file
64
apps/sam/c/Makefile.linux
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#
|
||||||
|
# This Makefile is compatible with GNU Make and should work on Linux (generic)
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Your operating system
|
||||||
|
#
|
||||||
|
|
||||||
|
OS = LINUX
|
||||||
|
|
||||||
|
#
|
||||||
|
# Directories
|
||||||
|
#
|
||||||
|
|
||||||
|
INCDIR = inc
|
||||||
|
LIBDIR = lib
|
||||||
|
OBJDIR = obj
|
||||||
|
SRCDIR = src
|
||||||
|
|
||||||
|
#
|
||||||
|
# Programs
|
||||||
|
#
|
||||||
|
|
||||||
|
AR = ar
|
||||||
|
CC = gcc
|
||||||
|
|
||||||
|
#
|
||||||
|
# Flags
|
||||||
|
#
|
||||||
|
|
||||||
|
CFLAGS = -g -march=i486 -O2 -pipe -std=c99 -Wall
|
||||||
|
CFLAGS += -DOS=$(OS)
|
||||||
|
CFLAGS += -I$(INCDIR)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Object files
|
||||||
|
#
|
||||||
|
|
||||||
|
OBJS = $(OBJDIR)/sam.o \
|
||||||
|
$(OBJDIR)/strl.o
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build rules
|
||||||
|
#
|
||||||
|
|
||||||
|
all: depend libsam
|
||||||
|
|
||||||
|
depend:
|
||||||
|
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
libsam: $(OBJS)
|
||||||
|
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Cleanup rules
|
||||||
|
#
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
|
||||||
|
|
||||||
|
tidy: clean
|
64
apps/sam/c/Makefile.mingw
Normal file
64
apps/sam/c/Makefile.mingw
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#
|
||||||
|
# This Makefile is compatible with GNU Make and should work on Windows (MingW)
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Your operating system
|
||||||
|
#
|
||||||
|
|
||||||
|
OS = MINGW
|
||||||
|
|
||||||
|
#
|
||||||
|
# Directories
|
||||||
|
#
|
||||||
|
|
||||||
|
INCDIR = inc
|
||||||
|
LIBDIR = lib
|
||||||
|
OBJDIR = obj
|
||||||
|
SRCDIR = src
|
||||||
|
|
||||||
|
#
|
||||||
|
# Programs
|
||||||
|
#
|
||||||
|
|
||||||
|
AR = C:\Dev-Cpp\bin\ar
|
||||||
|
CC = C:\Dev-Cpp\bin\gcc
|
||||||
|
|
||||||
|
#
|
||||||
|
# Flags
|
||||||
|
#
|
||||||
|
|
||||||
|
CFLAGS = -g -march=i486 -O2 -pipe -std=c99 -Wall
|
||||||
|
CFLAGS += -DOS=$(OS)
|
||||||
|
CFLAGS += -I$(INCDIR)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Object files
|
||||||
|
#
|
||||||
|
|
||||||
|
OBJS = $(OBJDIR)/sam.o \
|
||||||
|
$(OBJDIR)/strl.o
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build rules
|
||||||
|
#
|
||||||
|
|
||||||
|
all: depend libsam
|
||||||
|
|
||||||
|
depend:
|
||||||
|
$(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: $(SRCDIR)/%.c
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
libsam: $(OBJS)
|
||||||
|
$(AR) rcs $(LIBDIR)/libsam.a $(OBJS)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Cleanup rules
|
||||||
|
#
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -f $(LIBDIR)/libsam.a $(OBJDIR)/* .depend
|
||||||
|
|
||||||
|
tidy: clean
|
7
apps/sam/c/doc/donate.txt
Normal file
7
apps/sam/c/doc/donate.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
If you would like to make a donation to the author of this library, you can use
|
||||||
|
the following methods:
|
||||||
|
|
||||||
|
* E-Gold account number 1043280
|
||||||
|
* Paypal email mpc@innographx.com
|
||||||
|
|
||||||
|
If you want to use some other method, just ask.
|
27
apps/sam/c/doc/license.txt
Normal file
27
apps/sam/c/doc/license.txt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.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:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the author nor the names of any contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
9
apps/sam/c/doc/todo.txt
Normal file
9
apps/sam/c/doc/todo.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
I need to do these things:
|
||||||
|
|
||||||
|
* SAM raw support
|
||||||
|
* Write an instruction manual
|
||||||
|
|
||||||
|
Anyone can help with these things:
|
||||||
|
|
||||||
|
* Fix the example dgram-client.c
|
||||||
|
* Compile on as many platforms as possible
|
26
apps/sam/c/doc/whatsnew.txt
Normal file
26
apps/sam/c/doc/whatsnew.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
v1.15 2004-06-
|
||||||
|
* Fixed some fatal bugs in datagram handling
|
||||||
|
* Added another error return type named SAM_TOO_BIG - some functions now
|
||||||
|
return samerr_t instead of bool now
|
||||||
|
|
||||||
|
v1.10 2004-06-16
|
||||||
|
* Changed sam_strerror() to work the same as the standard library strerror()
|
||||||
|
* Ported to native MS Windows (uses the Mingw development environment)
|
||||||
|
* Fixed a probable bug in the Cygwin port
|
||||||
|
|
||||||
|
v1.05 2004-06-09
|
||||||
|
* Added an example datagram client/server program in the examples directory
|
||||||
|
* sam_read_buffer() now returns bool true if it read anything
|
||||||
|
* Added repliable datagram support - sam_connect() now has another argument
|
||||||
|
* Replaced strstr() with the more appropriate strncmp() in many places
|
||||||
|
* Fixed a parsing error for STREAM CLOSED
|
||||||
|
* Removed the old sam_naming_lookup() and renamed sam_naming_lookup_async()
|
||||||
|
to sam_naming_lookup() to replace it
|
||||||
|
* Fixed a bug in sam_stream_close() where a '\n' was not being sent after
|
||||||
|
the SAM command
|
||||||
|
* Fixed a bug where the stream ID was being improperly incremented in
|
||||||
|
sam_stream_connect()
|
||||||
|
* Added generic Linux Makefile for non-Debian distributions
|
||||||
|
|
||||||
|
v1.00 2004-06-02
|
||||||
|
* First public release
|
8
apps/sam/c/examples/build.bat
Normal file
8
apps/sam/c/examples/build.bat
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
del dgram-server.o dgram-server.exe
|
||||||
|
C:\Dev-Cpp\bin\gcc -I../inc -o dgram-server.o -c dgram-server.c
|
||||||
|
C:\Dev-Cpp\bin\gcc -I../inc -L../lib -o dgram-server.exe dgram-server.o -lsam -lwsock32
|
||||||
|
del dgram-client.o dgram-client.exe
|
||||||
|
C:\Dev-Cpp\bin\gcc -I../inc -o dgram-client.o -c dgram-client.c
|
||||||
|
C:\Dev-Cpp\bin\gcc -I../inc -L../lib -o dgram-client.exe dgram-client.o -lsam -lwsock32
|
8
apps/sam/c/examples/build.sh
Normal file
8
apps/sam/c/examples/build.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
rm dgram-server.o dgram-server
|
||||||
|
gcc -I../inc -o dgram-server.o -c dgram-server.c
|
||||||
|
gcc -I../inc -L../lib -o dgram-server dgram-server.o -lsam
|
||||||
|
rm dgram-client.o dgram-client
|
||||||
|
gcc -I../inc -o dgram-client.o -c dgram-client.c
|
||||||
|
gcc -I../inc -L../lib -o dgram-client dgram-client.o -lsam
|
125
apps/sam/c/examples/dgram-client.c
Normal file
125
apps/sam/c/examples/dgram-client.c
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.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:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the author nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sam.h"
|
||||||
|
|
||||||
|
static void dgramback(sam_pubkey_t dest, void *data, size_t size);
|
||||||
|
static void diedback(void);
|
||||||
|
static void logback(char *s);
|
||||||
|
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an extremely simple echo client which shows you how LibSAM
|
||||||
|
* datagrams work. We lookup the name 'dgram-server' then send some data to
|
||||||
|
* him. If everything works, we should get the same data back.
|
||||||
|
*/
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
samerr_t rc;
|
||||||
|
char errstr[SAM_ERRMSG_LEN];
|
||||||
|
|
||||||
|
/* Hook up the callback functions */
|
||||||
|
sam_dgramback = &dgramback;
|
||||||
|
sam_diedback = &diedback;
|
||||||
|
sam_logback = &logback;
|
||||||
|
sam_namingback = &namingback;
|
||||||
|
|
||||||
|
/* Connect to the SAM server */
|
||||||
|
rc = sam_connect("localhost", 7656, "dgram-client", SAM_DGRAM, 0);
|
||||||
|
if (rc != SAM_OK) {
|
||||||
|
fprintf(stderr, "SAM connection failed: %s\n", sam_strerror(rc));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* This is equivalent to doing a DNS lookup on the normal internet. Note
|
||||||
|
* that the dgram-server must already be running for this to work.
|
||||||
|
* When the lookup completes, we send them some data (see namingback()).
|
||||||
|
*/
|
||||||
|
sam_naming_lookup("dgram-server");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for something to happen, then invoke the appropriate callback
|
||||||
|
*/
|
||||||
|
while (true)
|
||||||
|
sam_read_buffer();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we receive some data, print it out to the screen
|
||||||
|
*/
|
||||||
|
static void dgramback(sam_pubkey_t dest, void *data, size_t size)
|
||||||
|
{
|
||||||
|
printf("Datagram received: %s\n", (char *)data);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is called whenever the SAM connection fails (like if the I2P router is
|
||||||
|
* shut down)
|
||||||
|
*/
|
||||||
|
static void diedback(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Lost SAM connection!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The logging callback prints any logging messages from LibSAM
|
||||||
|
*/
|
||||||
|
static void logback(char *s)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "LibSAM: %s\n", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When a name is resolved, send data to that destination address
|
||||||
|
*/
|
||||||
|
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result)
|
||||||
|
{
|
||||||
|
char *data = "Hello, invisible world!";
|
||||||
|
|
||||||
|
printf("I got %s's base 64 destination, so now I will send him some " \
|
||||||
|
"data...\n", name);
|
||||||
|
sam_dgram_send(pubkey, data, strlen(data));
|
||||||
|
/*
|
||||||
|
* ^^^ An extra NUL is appended to the data by LibSAM, so it is not
|
||||||
|
* necessary to send trailing NULs over the wire for strings. This doesn't
|
||||||
|
* cause problems with binary data, because the NUL isn't included in `size'
|
||||||
|
* in sam_dgramback().
|
||||||
|
* That is why we use strlen(data) instead of strlen(data) + 1.
|
||||||
|
*/
|
||||||
|
puts("Datagram sent");
|
||||||
|
}
|
109
apps/sam/c/examples/dgram-server.c
Normal file
109
apps/sam/c/examples/dgram-server.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.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:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the author nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sam.h"
|
||||||
|
|
||||||
|
static void dgramback(sam_pubkey_t dest, void *data, size_t size);
|
||||||
|
static void diedback(void);
|
||||||
|
static void logback(char *s);
|
||||||
|
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an extremely simple echo server which shows you how LibSAM
|
||||||
|
* datagrams work. We echo back every datagram that is sent to us.
|
||||||
|
*/
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
samerr_t rc;
|
||||||
|
char errstr[SAM_ERRMSG_LEN];
|
||||||
|
|
||||||
|
/* Hook up the callback functions */
|
||||||
|
sam_dgramback = &dgramback;
|
||||||
|
sam_diedback = &diedback;
|
||||||
|
sam_logback = &logback;
|
||||||
|
sam_namingback = &namingback;
|
||||||
|
|
||||||
|
/* Connect to the SAM server */
|
||||||
|
rc = sam_connect("127.0.0.1", 7656, "dgram-server", SAM_DGRAM, 0);
|
||||||
|
if (rc != SAM_OK) {
|
||||||
|
fprintf(stderr, "SAM connection failed: %s\n", sam_strerror(rc));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point we just keep polling the buffer, which causes the
|
||||||
|
* appropriate callbacks to be called whenever something happens
|
||||||
|
*/
|
||||||
|
while (true)
|
||||||
|
sam_read_buffer();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When we receive some data, we just ECHO the exact same data back to them
|
||||||
|
*/
|
||||||
|
static void dgramback(sam_pubkey_t dest, void *data, size_t size)
|
||||||
|
{
|
||||||
|
puts("Echoing datagram");
|
||||||
|
sam_dgram_send(dest, data, size);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is called whenever the SAM connection fails (like if the I2P router is
|
||||||
|
* shut down)
|
||||||
|
*/
|
||||||
|
static void diedback(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Lost SAM connection!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The logging callback prints any logging messages from LibSAM
|
||||||
|
*/
|
||||||
|
static void logback(char *s)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "LibSAM: %s\n", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not used, but the function has to be in the program anyway
|
||||||
|
*/
|
||||||
|
static void namingback(char *name, sam_pubkey_t pubkey, samerr_t result)
|
||||||
|
{
|
||||||
|
assert(false); /* we don't do any naming lookups in this program */
|
||||||
|
}
|
140
apps/sam/c/inc/platform.h
Normal file
140
apps/sam/c/inc/platform.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.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:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the author nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PLATFORM_H
|
||||||
|
#define PLATFORM_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Operating system
|
||||||
|
*/
|
||||||
|
#define FREEBSD 0 // FreeBSD (untested)
|
||||||
|
#define MINGW 1 // Windows native (Mingw)
|
||||||
|
#define LINUX 2 // Linux
|
||||||
|
#define CYGWIN 3 // Cygwin
|
||||||
|
|
||||||
|
#if OS == MINGW
|
||||||
|
#define INET_ADDRSTRLEN 16
|
||||||
|
#define NO_GETHOSTBYNAME2
|
||||||
|
#define NO_INET_ATON /* implies NO_INET_PTON */
|
||||||
|
#define NO_INET_NTOP
|
||||||
|
#define NO_STRL
|
||||||
|
#define NO_Z_FORMAT
|
||||||
|
#define WINSOCK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if OS == LINUX
|
||||||
|
#define NO_GETHOSTBYNAME2
|
||||||
|
#define NO_STRL
|
||||||
|
#define NO_Z_FORMAT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if OS == CYGWIN
|
||||||
|
#define FAST32_IS_LONG
|
||||||
|
#define INET_ADDRSTRLEN 16
|
||||||
|
#define NO_GETHOSTBYNAME2
|
||||||
|
#define NO_INET_NTOP
|
||||||
|
#define NO_INET_PTON
|
||||||
|
#define NO_SNPRINTF
|
||||||
|
#define NO_STRL
|
||||||
|
#define NO_VSNPRINTF
|
||||||
|
#define NO_Z_FORMAT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standard C99 includes - if your compiler doesn't have these, it's time to
|
||||||
|
* upgrade
|
||||||
|
*/
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* System includes
|
||||||
|
*/
|
||||||
|
#ifdef WINSOCK
|
||||||
|
#include <winsock.h>
|
||||||
|
#else
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#ifndef WINSOCK
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#if defined NO_SNPRINTF || defined NO_VSNPRINTF
|
||||||
|
#include "snprintf.h"
|
||||||
|
#endif
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef NO_STRL
|
||||||
|
#include "strl.h"
|
||||||
|
#endif
|
||||||
|
#ifdef WINSOCK
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Platform-dependent variable types
|
||||||
|
*/
|
||||||
|
#ifdef WINSOCK
|
||||||
|
typedef SOCKET socket_t;
|
||||||
|
typedef signed long ssize_t;
|
||||||
|
#else
|
||||||
|
typedef int socket_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prints out the file name, line number, and function name before log message
|
||||||
|
*/
|
||||||
|
#define SAMLOG(format, ...) sam_log("%s:%d:%s: " \
|
||||||
|
format, __FILE__, __LINE__, __func__, __VA_ARGS__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the same as above, except that it doesn't accept any va args
|
||||||
|
*/
|
||||||
|
#define SAMLOGS(str) sam_log("%s:%d:%s: " str, __FILE__, __LINE__, __func__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set this to true if you want the raw SAM commands to be printed on stdout
|
||||||
|
* (useful for debugging)
|
||||||
|
*/
|
||||||
|
#define SAM_WIRETAP false
|
||||||
|
#if SAM_WIRETAP
|
||||||
|
#include <ctype.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PLATFORM_H */
|
123
apps/sam/c/inc/sam.h
Normal file
123
apps/sam/c/inc/sam.h
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.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:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the author nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SAM_H
|
||||||
|
#define SAM_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lengths
|
||||||
|
*/
|
||||||
|
#define SAM_CMD_LEN 128 /* the maximum length a SAM command can be */
|
||||||
|
#define SAM_DGRAM_PAYLOAD_MAX 31774 /* max size of a single datagram packet */
|
||||||
|
#define SAM_ERRMSG_LEN 23 /* the longest message returned from sam_strerror */
|
||||||
|
#define SAM_LOGMSG_LEN 256 /* the longest log message */
|
||||||
|
#define SAM_NAME_LEN 256 /* the longest `name' arg for naming lookup callback*/
|
||||||
|
#define SAM_STREAM_PAYLOAD_MAX 32768 /* max size of a single stream packet */
|
||||||
|
#define SAM_PKCMD_LEN (SAM_PUBKEY_LEN + SAM_CMD_LEN)/*a public key SAM command*/
|
||||||
|
#define SAM_PUBKEY_LEN 517 /* it's actually 516, but +1 for '\0' */
|
||||||
|
#define SAM_REPLY_LEN 1024 /* the maximum length a SAM non-data reply can be */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shorten some standard variable types
|
||||||
|
*/
|
||||||
|
typedef signed char schar_t;
|
||||||
|
typedef unsigned char uchar_t;
|
||||||
|
typedef unsigned int uint_t;
|
||||||
|
typedef unsigned long ulong_t;
|
||||||
|
typedef unsigned short ushort_t;
|
||||||
|
|
||||||
|
typedef enum {SAM_STREAM, SAM_DGRAM, SAM_RAW} sam_conn_t; /* SAM connection */
|
||||||
|
|
||||||
|
typedef char sam_pubkey_t[SAM_PUBKEY_LEN]; /* base 64 public key */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *data;
|
||||||
|
size_t size;
|
||||||
|
} sam_sendq_t; /* sending queue to encourage large stream packet sizes */
|
||||||
|
|
||||||
|
typedef int_fast32_t sam_sid_t; /* stream id number */
|
||||||
|
|
||||||
|
typedef enum { /* see sam_strerror() for detailed descriptions of these */
|
||||||
|
/* error codes from SAM itself (SAM_OK is not an actual "error") */
|
||||||
|
SAM_OK, SAM_CANT_REACH_PEER, SAM_DUPLICATED_DEST, SAM_I2P_ERROR,
|
||||||
|
SAM_INVALID_KEY, SAM_KEY_NOT_FOUND, SAM_PEER_NOT_FOUND, SAM_TIMEOUT,
|
||||||
|
SAM_UNKNOWN,
|
||||||
|
/* error codes from libsam */
|
||||||
|
SAM_BAD_VERSION, SAM_CALLBACKS_UNSET, SAM_SOCKET_ERROR, SAM_TOO_BIG
|
||||||
|
} samerr_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* SAM controls */
|
||||||
|
extern bool sam_close(void);
|
||||||
|
extern samerr_t sam_connect(const char *samhost, uint16_t samport,
|
||||||
|
const char *destname, sam_conn_t style, uint_t tunneldepth);
|
||||||
|
extern void sam_naming_lookup(const char *name);
|
||||||
|
extern bool sam_read_buffer(void);
|
||||||
|
extern char *sam_strerror(samerr_t code);
|
||||||
|
/* SAM controls - callbacks */
|
||||||
|
extern void (*sam_diedback)(void);
|
||||||
|
extern void (*sam_logback)(char *str);
|
||||||
|
extern void (*sam_namingback)(char *name, sam_pubkey_t pubkey,
|
||||||
|
samerr_t result);
|
||||||
|
|
||||||
|
/* Stream commands */
|
||||||
|
extern void sam_stream_close(sam_sid_t stream_id);
|
||||||
|
extern sam_sid_t sam_stream_connect(const sam_pubkey_t dest);
|
||||||
|
extern samerr_t sam_stream_send(sam_sid_t stream_id, const void *data,
|
||||||
|
size_t size);
|
||||||
|
/* Stream commands - callbacks */
|
||||||
|
extern void (*sam_closeback)(sam_sid_t stream_id, samerr_t reason);
|
||||||
|
extern void (*sam_connectback)(sam_sid_t stream_id, sam_pubkey_t dest);
|
||||||
|
extern void (*sam_databack)(sam_sid_t stream_id, void *data, size_t size);
|
||||||
|
extern void (*sam_statusback)(sam_sid_t stream_id, samerr_t result);
|
||||||
|
|
||||||
|
/* Stream send queue */
|
||||||
|
extern samerr_t sam_sendq_add(sam_sendq_t *sendq, const void *data,
|
||||||
|
size_t dsize);
|
||||||
|
extern sam_sendq_t *sam_sendq_create(void);
|
||||||
|
extern void sam_sendq_send(sam_sendq_t *sendq, sam_sid_t stream_id);
|
||||||
|
|
||||||
|
/* Datagram commands */
|
||||||
|
extern samerr_t sam_dgram_send(const sam_pubkey_t dest, const void *data,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
/* Datagram commands - callbacks */
|
||||||
|
extern void (*sam_dgramback)(sam_pubkey_t dest, void *data, size_t size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* SAM_H */
|
49
apps/sam/c/inc/snprintf.h
Normal file
49
apps/sam/c/inc/snprintf.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.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:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the author nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: The snprintf.c file retains its original license (at the top of
|
||||||
|
* snprintf.c)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SNPRINTF_H
|
||||||
|
#define SNPRINTF_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdarg.h> /* for va_list */
|
||||||
|
int snprintf (char *str, size_t count, const char *fmt, ...);
|
||||||
|
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* SNPRINTF_H */
|
47
apps/sam/c/inc/strl.h
Normal file
47
apps/sam/c/inc/strl.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.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:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the author nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: The strl.c file retains its original license (at the top of strl.c)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STRL_H
|
||||||
|
#define STRL_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern size_t strlcat(char *dst, const char *src, size_t siz);
|
||||||
|
extern size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* STRL_H */
|
1047
apps/sam/c/src/sam.c
Normal file
1047
apps/sam/c/src/sam.c
Normal file
File diff suppressed because it is too large
Load Diff
851
apps/sam/c/src/snprintf.c
Normal file
851
apps/sam/c/src/snprintf.c
Normal file
@ -0,0 +1,851 @@
|
|||||||
|
/*
|
||||||
|
* Copyright Patrick Powell 1995
|
||||||
|
* This code is based on code written by Patrick Powell (papowell@astart.com)
|
||||||
|
* It may be used for any purpose as long as this notice remains intact
|
||||||
|
* on all source code distributions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**************************************************************
|
||||||
|
* Original:
|
||||||
|
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
|
||||||
|
* A bombproof version of doprnt (dopr) included.
|
||||||
|
* Sigh. This sort of thing is always nasty do deal with. Note that
|
||||||
|
* the version here does not include floating point...
|
||||||
|
*
|
||||||
|
* snprintf() is used instead of sprintf() as it does limit checks
|
||||||
|
* for string length. This covers a nasty loophole.
|
||||||
|
*
|
||||||
|
* The other functions are there to prevent NULL pointers from
|
||||||
|
* causing nast effects.
|
||||||
|
*
|
||||||
|
* More Recently:
|
||||||
|
* Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
|
||||||
|
* This was ugly. It is still ugly. I opted out of floating point
|
||||||
|
* numbers, but the formatter understands just about everything
|
||||||
|
* from the normal C string format, at least as far as I can tell from
|
||||||
|
* the Solaris 2.5 printf(3S) man page.
|
||||||
|
*
|
||||||
|
* Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
|
||||||
|
* Ok, added some minimal floating point support, which means this
|
||||||
|
* probably requires libm on most operating systems. Don't yet
|
||||||
|
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
|
||||||
|
* was pretty badly broken, it just wasn't being exercised in ways
|
||||||
|
* which showed it, so that's been fixed. Also, formated the code
|
||||||
|
* to mutt conventions, and removed dead code left over from the
|
||||||
|
* original. Also, there is now a builtin-test, just compile with:
|
||||||
|
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
|
||||||
|
* and run snprintf for results.
|
||||||
|
*
|
||||||
|
* Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
|
||||||
|
* The PGP code was using unsigned hexadecimal formats.
|
||||||
|
* Unfortunately, unsigned formats simply didn't work.
|
||||||
|
*
|
||||||
|
* Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
|
||||||
|
* The original code assumed that both snprintf() and vsnprintf() were
|
||||||
|
* missing. Some systems only have snprintf() but not vsnprintf(), so
|
||||||
|
* the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
|
||||||
|
*
|
||||||
|
* Andrew Tridgell (tridge@samba.org) Oct 1998
|
||||||
|
* fixed handling of %.0f
|
||||||
|
* added test for HAVE_LONG_DOUBLE
|
||||||
|
*
|
||||||
|
* Russ Allbery <rra@stanford.edu> 2000-08-26
|
||||||
|
* fixed return value to comply with C99
|
||||||
|
* fixed handling of snprintf(NULL, ...)
|
||||||
|
*
|
||||||
|
* Hrvoje Niksic <hniksic@arsdigita.com> 2000-11-04
|
||||||
|
* include <stdio.h> for NULL.
|
||||||
|
* added support for long long.
|
||||||
|
* don't declare argument types to (v)snprintf if stdarg is not used.
|
||||||
|
*
|
||||||
|
**************************************************************/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
# define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* varargs declarations: */
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#define HAVE_STDARGS /* let's hope that works everywhere (mj) */
|
||||||
|
#define VA_LOCAL_DECL va_list ap
|
||||||
|
#define VA_START(f) va_start(ap, f)
|
||||||
|
#define VA_SHIFT(v,t) ; /* no-op for ANSI */
|
||||||
|
#define VA_END va_end(ap)
|
||||||
|
|
||||||
|
#ifdef HAVE_LONG_DOUBLE
|
||||||
|
#define LDOUBLE long double
|
||||||
|
#else
|
||||||
|
#define LDOUBLE double
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LONG_LONG
|
||||||
|
# define LLONG long long
|
||||||
|
#else
|
||||||
|
# define LLONG long
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int snprintf (char *str, size_t count, const char *fmt, ...);
|
||||||
|
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
|
||||||
|
|
||||||
|
static int dopr (char *buffer, size_t maxlen, const char *format,
|
||||||
|
va_list args);
|
||||||
|
static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
|
||||||
|
char *value, int flags, int min, int max);
|
||||||
|
static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
|
||||||
|
LLONG value, int base, int min, int max, int flags);
|
||||||
|
static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||||
|
LDOUBLE fvalue, int min, int max, int flags);
|
||||||
|
static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dopr(): poor man's version of doprintf
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* format read states */
|
||||||
|
#define DP_S_DEFAULT 0
|
||||||
|
#define DP_S_FLAGS 1
|
||||||
|
#define DP_S_MIN 2
|
||||||
|
#define DP_S_DOT 3
|
||||||
|
#define DP_S_MAX 4
|
||||||
|
#define DP_S_MOD 5
|
||||||
|
#define DP_S_MOD_L 6
|
||||||
|
#define DP_S_CONV 7
|
||||||
|
#define DP_S_DONE 8
|
||||||
|
|
||||||
|
/* format flags - Bits */
|
||||||
|
#define DP_F_MINUS (1 << 0)
|
||||||
|
#define DP_F_PLUS (1 << 1)
|
||||||
|
#define DP_F_SPACE (1 << 2)
|
||||||
|
#define DP_F_NUM (1 << 3)
|
||||||
|
#define DP_F_ZERO (1 << 4)
|
||||||
|
#define DP_F_UP (1 << 5)
|
||||||
|
#define DP_F_UNSIGNED (1 << 6)
|
||||||
|
|
||||||
|
/* Conversion Flags */
|
||||||
|
#define DP_C_SHORT 1
|
||||||
|
#define DP_C_LONG 2
|
||||||
|
#define DP_C_LLONG 3
|
||||||
|
#define DP_C_LDOUBLE 4
|
||||||
|
|
||||||
|
#define char_to_int(p) (p - '0')
|
||||||
|
#define MAX(p,q) ((p >= q) ? p : q)
|
||||||
|
#define MIN(p,q) ((p <= q) ? p : q)
|
||||||
|
|
||||||
|
static int dopr (char *buffer, size_t maxlen, const char *format, va_list args)
|
||||||
|
{
|
||||||
|
char ch;
|
||||||
|
LLONG value;
|
||||||
|
LDOUBLE fvalue;
|
||||||
|
char *strvalue;
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
int state;
|
||||||
|
int flags;
|
||||||
|
int cflags;
|
||||||
|
int total;
|
||||||
|
size_t currlen;
|
||||||
|
|
||||||
|
state = DP_S_DEFAULT;
|
||||||
|
currlen = flags = cflags = min = 0;
|
||||||
|
max = -1;
|
||||||
|
ch = *format++;
|
||||||
|
total = 0;
|
||||||
|
|
||||||
|
while (state != DP_S_DONE)
|
||||||
|
{
|
||||||
|
if (ch == '\0')
|
||||||
|
state = DP_S_DONE;
|
||||||
|
|
||||||
|
switch(state)
|
||||||
|
{
|
||||||
|
case DP_S_DEFAULT:
|
||||||
|
if (ch == '%')
|
||||||
|
state = DP_S_FLAGS;
|
||||||
|
else
|
||||||
|
total += dopr_outch (buffer, &currlen, maxlen, ch);
|
||||||
|
ch = *format++;
|
||||||
|
break;
|
||||||
|
case DP_S_FLAGS:
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '-':
|
||||||
|
flags |= DP_F_MINUS;
|
||||||
|
ch = *format++;
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
flags |= DP_F_PLUS;
|
||||||
|
ch = *format++;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
flags |= DP_F_SPACE;
|
||||||
|
ch = *format++;
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
flags |= DP_F_NUM;
|
||||||
|
ch = *format++;
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
flags |= DP_F_ZERO;
|
||||||
|
ch = *format++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
state = DP_S_MIN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DP_S_MIN:
|
||||||
|
if (isdigit((unsigned char)ch))
|
||||||
|
{
|
||||||
|
min = 10*min + char_to_int (ch);
|
||||||
|
ch = *format++;
|
||||||
|
}
|
||||||
|
else if (ch == '*')
|
||||||
|
{
|
||||||
|
min = va_arg (args, int);
|
||||||
|
ch = *format++;
|
||||||
|
state = DP_S_DOT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
state = DP_S_DOT;
|
||||||
|
break;
|
||||||
|
case DP_S_DOT:
|
||||||
|
if (ch == '.')
|
||||||
|
{
|
||||||
|
state = DP_S_MAX;
|
||||||
|
ch = *format++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
state = DP_S_MOD;
|
||||||
|
break;
|
||||||
|
case DP_S_MAX:
|
||||||
|
if (isdigit((unsigned char)ch))
|
||||||
|
{
|
||||||
|
if (max < 0)
|
||||||
|
max = 0;
|
||||||
|
max = 10*max + char_to_int (ch);
|
||||||
|
ch = *format++;
|
||||||
|
}
|
||||||
|
else if (ch == '*')
|
||||||
|
{
|
||||||
|
max = va_arg (args, int);
|
||||||
|
ch = *format++;
|
||||||
|
state = DP_S_MOD;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
state = DP_S_MOD;
|
||||||
|
break;
|
||||||
|
case DP_S_MOD:
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case 'h':
|
||||||
|
cflags = DP_C_SHORT;
|
||||||
|
ch = *format++;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
cflags = DP_C_LONG;
|
||||||
|
ch = *format++;
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
cflags = DP_C_LDOUBLE;
|
||||||
|
ch = *format++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cflags != DP_C_LONG)
|
||||||
|
state = DP_S_CONV;
|
||||||
|
else
|
||||||
|
state = DP_S_MOD_L;
|
||||||
|
break;
|
||||||
|
case DP_S_MOD_L:
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case 'l':
|
||||||
|
cflags = DP_C_LLONG;
|
||||||
|
ch = *format++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = DP_S_CONV;
|
||||||
|
break;
|
||||||
|
case DP_S_CONV:
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case 'd':
|
||||||
|
case 'i':
|
||||||
|
if (cflags == DP_C_SHORT)
|
||||||
|
value = (short int) va_arg (args, int);
|
||||||
|
else if (cflags == DP_C_LONG)
|
||||||
|
value = va_arg (args, long int);
|
||||||
|
else if (cflags == DP_C_LLONG)
|
||||||
|
value = va_arg (args, LLONG);
|
||||||
|
else
|
||||||
|
value = va_arg (args, int);
|
||||||
|
total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
flags |= DP_F_UNSIGNED;
|
||||||
|
if (cflags == DP_C_SHORT)
|
||||||
|
value = (unsigned short int) va_arg (args, unsigned int);
|
||||||
|
else if (cflags == DP_C_LONG)
|
||||||
|
value = va_arg (args, unsigned long int);
|
||||||
|
else if (cflags == DP_C_LLONG)
|
||||||
|
value = va_arg (args, unsigned LLONG);
|
||||||
|
else
|
||||||
|
value = va_arg (args, unsigned int);
|
||||||
|
total += fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
flags |= DP_F_UNSIGNED;
|
||||||
|
if (cflags == DP_C_SHORT)
|
||||||
|
value = (unsigned short int) va_arg (args, unsigned int);
|
||||||
|
else if (cflags == DP_C_LONG)
|
||||||
|
value = va_arg (args, unsigned long int);
|
||||||
|
else if (cflags == DP_C_LLONG)
|
||||||
|
value = va_arg (args, unsigned LLONG);
|
||||||
|
else
|
||||||
|
value = va_arg (args, unsigned int);
|
||||||
|
total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
flags |= DP_F_UP;
|
||||||
|
case 'x':
|
||||||
|
flags |= DP_F_UNSIGNED;
|
||||||
|
if (cflags == DP_C_SHORT)
|
||||||
|
value = (unsigned short int) va_arg (args, unsigned int);
|
||||||
|
else if (cflags == DP_C_LONG)
|
||||||
|
value = va_arg (args, unsigned long int);
|
||||||
|
else if (cflags == DP_C_LLONG)
|
||||||
|
value = va_arg (args, unsigned LLONG);
|
||||||
|
else
|
||||||
|
value = va_arg (args, unsigned int);
|
||||||
|
total += fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
if (cflags == DP_C_LDOUBLE)
|
||||||
|
fvalue = va_arg (args, LDOUBLE);
|
||||||
|
else
|
||||||
|
fvalue = va_arg (args, double);
|
||||||
|
/* um, floating point? */
|
||||||
|
total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
flags |= DP_F_UP;
|
||||||
|
case 'e':
|
||||||
|
if (cflags == DP_C_LDOUBLE)
|
||||||
|
fvalue = va_arg (args, LDOUBLE);
|
||||||
|
else
|
||||||
|
fvalue = va_arg (args, double);
|
||||||
|
break;
|
||||||
|
case 'G':
|
||||||
|
flags |= DP_F_UP;
|
||||||
|
case 'g':
|
||||||
|
if (cflags == DP_C_LDOUBLE)
|
||||||
|
fvalue = va_arg (args, LDOUBLE);
|
||||||
|
else
|
||||||
|
fvalue = va_arg (args, double);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
total += dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
strvalue = va_arg (args, char *);
|
||||||
|
total += fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
strvalue = va_arg (args, void *);
|
||||||
|
total += fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min,
|
||||||
|
max, flags);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
if (cflags == DP_C_SHORT)
|
||||||
|
{
|
||||||
|
short int *num;
|
||||||
|
num = va_arg (args, short int *);
|
||||||
|
*num = currlen;
|
||||||
|
}
|
||||||
|
else if (cflags == DP_C_LONG)
|
||||||
|
{
|
||||||
|
long int *num;
|
||||||
|
num = va_arg (args, long int *);
|
||||||
|
*num = currlen;
|
||||||
|
}
|
||||||
|
else if (cflags == DP_C_LLONG)
|
||||||
|
{
|
||||||
|
LLONG *num;
|
||||||
|
num = va_arg (args, LLONG *);
|
||||||
|
*num = currlen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int *num;
|
||||||
|
num = va_arg (args, int *);
|
||||||
|
*num = currlen;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
total += dopr_outch (buffer, &currlen, maxlen, ch);
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
/* not supported yet, treat as next char */
|
||||||
|
ch = *format++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Unknown, skip */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ch = *format++;
|
||||||
|
state = DP_S_DEFAULT;
|
||||||
|
flags = cflags = min = 0;
|
||||||
|
max = -1;
|
||||||
|
break;
|
||||||
|
case DP_S_DONE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* hmm? */
|
||||||
|
break; /* some picky compilers need this */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buffer != NULL)
|
||||||
|
{
|
||||||
|
if (currlen < maxlen - 1)
|
||||||
|
buffer[currlen] = '\0';
|
||||||
|
else
|
||||||
|
buffer[maxlen - 1] = '\0';
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
|
||||||
|
char *value, int flags, int min, int max)
|
||||||
|
{
|
||||||
|
int padlen, strln; /* amount to pad */
|
||||||
|
int cnt = 0;
|
||||||
|
int total = 0;
|
||||||
|
char null[] = "<NULL>";
|
||||||
|
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (strln = 0; value[strln]; ++strln); /* strlen */
|
||||||
|
if (max >= 0 && max < strln)
|
||||||
|
strln = max;
|
||||||
|
padlen = min - strln;
|
||||||
|
if (padlen < 0)
|
||||||
|
padlen = 0;
|
||||||
|
if (flags & DP_F_MINUS)
|
||||||
|
padlen = -padlen; /* Left Justify */
|
||||||
|
|
||||||
|
while (padlen > 0)
|
||||||
|
{
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||||
|
--padlen;
|
||||||
|
}
|
||||||
|
while (*value && ((max < 0) || (cnt < max)))
|
||||||
|
{
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, *value++);
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
while (padlen < 0)
|
||||||
|
{
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||||
|
++padlen;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
|
||||||
|
|
||||||
|
static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
|
||||||
|
LLONG value, int base, int min, int max, int flags)
|
||||||
|
{
|
||||||
|
int signvalue = 0;
|
||||||
|
unsigned LLONG uvalue;
|
||||||
|
char convert[24];
|
||||||
|
unsigned int place = 0;
|
||||||
|
int spadlen = 0; /* amount to space pad */
|
||||||
|
int zpadlen = 0; /* amount to zero pad */
|
||||||
|
const char *digits;
|
||||||
|
int total = 0;
|
||||||
|
|
||||||
|
if (max < 0)
|
||||||
|
max = 0;
|
||||||
|
|
||||||
|
uvalue = value;
|
||||||
|
|
||||||
|
if(!(flags & DP_F_UNSIGNED))
|
||||||
|
{
|
||||||
|
if( value < 0 ) {
|
||||||
|
signvalue = '-';
|
||||||
|
uvalue = -value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
|
||||||
|
signvalue = '+';
|
||||||
|
else
|
||||||
|
if (flags & DP_F_SPACE)
|
||||||
|
signvalue = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & DP_F_UP)
|
||||||
|
/* Should characters be upper case? */
|
||||||
|
digits = "0123456789ABCDEF";
|
||||||
|
else
|
||||||
|
digits = "0123456789abcdef";
|
||||||
|
|
||||||
|
do {
|
||||||
|
convert[place++] = digits[uvalue % (unsigned)base];
|
||||||
|
uvalue = (uvalue / (unsigned)base );
|
||||||
|
} while(uvalue && (place < sizeof (convert)));
|
||||||
|
if (place == sizeof (convert)) place--;
|
||||||
|
convert[place] = 0;
|
||||||
|
|
||||||
|
zpadlen = max - place;
|
||||||
|
spadlen = min - MAX ((unsigned int)max, place) - (signvalue ? 1 : 0);
|
||||||
|
if (zpadlen < 0) zpadlen = 0;
|
||||||
|
if (spadlen < 0) spadlen = 0;
|
||||||
|
if (flags & DP_F_ZERO)
|
||||||
|
{
|
||||||
|
zpadlen = MAX(zpadlen, spadlen);
|
||||||
|
spadlen = 0;
|
||||||
|
}
|
||||||
|
if (flags & DP_F_MINUS)
|
||||||
|
spadlen = -spadlen; /* Left Justifty */
|
||||||
|
|
||||||
|
#ifdef DEBUG_SNPRINTF
|
||||||
|
dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
|
||||||
|
zpadlen, spadlen, min, max, place));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Spaces */
|
||||||
|
while (spadlen > 0)
|
||||||
|
{
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||||
|
--spadlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sign */
|
||||||
|
if (signvalue)
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, signvalue);
|
||||||
|
|
||||||
|
/* Zeros */
|
||||||
|
if (zpadlen > 0)
|
||||||
|
{
|
||||||
|
while (zpadlen > 0)
|
||||||
|
{
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, '0');
|
||||||
|
--zpadlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Digits */
|
||||||
|
while (place > 0)
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, convert[--place]);
|
||||||
|
|
||||||
|
/* Left Justified spaces */
|
||||||
|
while (spadlen < 0) {
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||||
|
++spadlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LDOUBLE abs_val (LDOUBLE value)
|
||||||
|
{
|
||||||
|
LDOUBLE result = value;
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
result = -value;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LDOUBLE pow10 (int exp)
|
||||||
|
{
|
||||||
|
LDOUBLE result = 1;
|
||||||
|
|
||||||
|
while (exp)
|
||||||
|
{
|
||||||
|
result *= 10;
|
||||||
|
exp--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long round (LDOUBLE value)
|
||||||
|
{
|
||||||
|
long intpart;
|
||||||
|
|
||||||
|
intpart = value;
|
||||||
|
value = value - intpart;
|
||||||
|
if (value >= 0.5)
|
||||||
|
intpart++;
|
||||||
|
|
||||||
|
return intpart;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||||
|
LDOUBLE fvalue, int min, int max, int flags)
|
||||||
|
{
|
||||||
|
int signvalue = 0;
|
||||||
|
LDOUBLE ufvalue;
|
||||||
|
char iconvert[20];
|
||||||
|
char fconvert[20];
|
||||||
|
int iplace = 0;
|
||||||
|
int fplace = 0;
|
||||||
|
int padlen = 0; /* amount to pad */
|
||||||
|
int zpadlen = 0;
|
||||||
|
int caps = 0;
|
||||||
|
int total = 0;
|
||||||
|
LLONG intpart;
|
||||||
|
LLONG fracpart;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AIX manpage says the default is 0, but Solaris says the default
|
||||||
|
* is 6, and sprintf on AIX defaults to 6
|
||||||
|
*/
|
||||||
|
if (max < 0)
|
||||||
|
max = 6;
|
||||||
|
|
||||||
|
ufvalue = abs_val (fvalue);
|
||||||
|
|
||||||
|
if (fvalue < 0)
|
||||||
|
signvalue = '-';
|
||||||
|
else
|
||||||
|
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
|
||||||
|
signvalue = '+';
|
||||||
|
else
|
||||||
|
if (flags & DP_F_SPACE)
|
||||||
|
signvalue = ' ';
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
intpart = ufvalue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sorry, we only support 9 digits past the decimal because of our
|
||||||
|
* conversion method
|
||||||
|
*/
|
||||||
|
if (max > 9)
|
||||||
|
max = 9;
|
||||||
|
|
||||||
|
/* We "cheat" by converting the fractional part to integer by
|
||||||
|
* multiplying by a factor of 10
|
||||||
|
*/
|
||||||
|
fracpart = round ((pow10 (max)) * (ufvalue - intpart));
|
||||||
|
|
||||||
|
if (fracpart >= pow10 (max))
|
||||||
|
{
|
||||||
|
intpart++;
|
||||||
|
fracpart -= pow10 (max);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_SNPRINTF
|
||||||
|
dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Convert integer part */
|
||||||
|
do {
|
||||||
|
iconvert[iplace++] =
|
||||||
|
(caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
|
||||||
|
intpart = (intpart / 10);
|
||||||
|
} while(intpart && (iplace < 20));
|
||||||
|
if (iplace == 20) iplace--;
|
||||||
|
iconvert[iplace] = 0;
|
||||||
|
|
||||||
|
/* Convert fractional part */
|
||||||
|
do {
|
||||||
|
fconvert[fplace++] =
|
||||||
|
(caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
|
||||||
|
fracpart = (fracpart / 10);
|
||||||
|
} while(fracpart && (fplace < 20));
|
||||||
|
if (fplace == 20) fplace--;
|
||||||
|
fconvert[fplace] = 0;
|
||||||
|
|
||||||
|
/* -1 for decimal point, another -1 if we are printing a sign */
|
||||||
|
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
|
||||||
|
zpadlen = max - fplace;
|
||||||
|
if (zpadlen < 0)
|
||||||
|
zpadlen = 0;
|
||||||
|
if (padlen < 0)
|
||||||
|
padlen = 0;
|
||||||
|
if (flags & DP_F_MINUS)
|
||||||
|
padlen = -padlen; /* Left Justifty */
|
||||||
|
|
||||||
|
if ((flags & DP_F_ZERO) && (padlen > 0))
|
||||||
|
{
|
||||||
|
if (signvalue)
|
||||||
|
{
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, signvalue);
|
||||||
|
--padlen;
|
||||||
|
signvalue = 0;
|
||||||
|
}
|
||||||
|
while (padlen > 0)
|
||||||
|
{
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, '0');
|
||||||
|
--padlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (padlen > 0)
|
||||||
|
{
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||||
|
--padlen;
|
||||||
|
}
|
||||||
|
if (signvalue)
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, signvalue);
|
||||||
|
|
||||||
|
while (iplace > 0)
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decimal point. This should probably use locale to find the correct
|
||||||
|
* char to print out.
|
||||||
|
*/
|
||||||
|
if (max > 0)
|
||||||
|
{
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, '.');
|
||||||
|
|
||||||
|
while (fplace > 0)
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (zpadlen > 0)
|
||||||
|
{
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, '0');
|
||||||
|
--zpadlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (padlen < 0)
|
||||||
|
{
|
||||||
|
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||||
|
++padlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
|
||||||
|
{
|
||||||
|
if (*currlen + 1 < maxlen)
|
||||||
|
buffer[(*currlen)++] = c;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
if (str != NULL)
|
||||||
|
str[0] = 0;
|
||||||
|
return dopr(str, count, fmt, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* VARARGS3 */
|
||||||
|
#ifdef HAVE_STDARGS
|
||||||
|
int snprintf (char *str,size_t count,const char *fmt,...)
|
||||||
|
#else
|
||||||
|
int snprintf (va_alist) va_dcl
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifndef HAVE_STDARGS
|
||||||
|
char *str;
|
||||||
|
size_t count;
|
||||||
|
char *fmt;
|
||||||
|
#endif
|
||||||
|
VA_LOCAL_DECL;
|
||||||
|
int total;
|
||||||
|
|
||||||
|
VA_START (fmt);
|
||||||
|
VA_SHIFT (str, char *);
|
||||||
|
VA_SHIFT (count, size_t );
|
||||||
|
VA_SHIFT (fmt, char *);
|
||||||
|
total = vsnprintf(str, count, fmt, ap);
|
||||||
|
VA_END;
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TEST_SNPRINTF
|
||||||
|
#ifndef LONG_STRING
|
||||||
|
#define LONG_STRING 1024
|
||||||
|
#endif
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
char buf1[LONG_STRING];
|
||||||
|
char buf2[LONG_STRING];
|
||||||
|
char *fp_fmt[] = {
|
||||||
|
"%-1.5f",
|
||||||
|
"%1.5f",
|
||||||
|
"%123.9f",
|
||||||
|
"%10.5f",
|
||||||
|
"% 10.5f",
|
||||||
|
"%+22.9f",
|
||||||
|
"%+4.9f",
|
||||||
|
"%01.3f",
|
||||||
|
"%4f",
|
||||||
|
"%3.1f",
|
||||||
|
"%3.2f",
|
||||||
|
"%.0f",
|
||||||
|
"%.1f",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
|
||||||
|
0.9996, 1.996, 4.136, 0};
|
||||||
|
char *int_fmt[] = {
|
||||||
|
"%-1.5d",
|
||||||
|
"%1.5d",
|
||||||
|
"%123.9d",
|
||||||
|
"%5.5d",
|
||||||
|
"%10.5d",
|
||||||
|
"% 10.5d",
|
||||||
|
"%+22.33d",
|
||||||
|
"%01.3d",
|
||||||
|
"%4d",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
|
||||||
|
int x, y;
|
||||||
|
int fail = 0;
|
||||||
|
int num = 0;
|
||||||
|
|
||||||
|
printf ("Testing snprintf format codes against system sprintf...\n");
|
||||||
|
|
||||||
|
for (x = 0; fp_fmt[x] != NULL ; x++)
|
||||||
|
for (y = 0; fp_nums[y] != 0 ; y++)
|
||||||
|
{
|
||||||
|
snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);
|
||||||
|
sprintf (buf2, fp_fmt[x], fp_nums[y]);
|
||||||
|
if (strcmp (buf1, buf2))
|
||||||
|
{
|
||||||
|
printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
|
||||||
|
fp_fmt[x], buf1, buf2);
|
||||||
|
fail++;
|
||||||
|
}
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (x = 0; int_fmt[x] != NULL ; x++)
|
||||||
|
for (y = 0; int_nums[y] != 0 ; y++)
|
||||||
|
{
|
||||||
|
snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);
|
||||||
|
sprintf (buf2, int_fmt[x], int_nums[y]);
|
||||||
|
if (strcmp (buf1, buf2))
|
||||||
|
{
|
||||||
|
printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
|
||||||
|
int_fmt[x], buf1, buf2);
|
||||||
|
fail++;
|
||||||
|
}
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
printf ("%d tests failed out of %d.\n", fail, num);
|
||||||
|
}
|
||||||
|
#endif /* SNPRINTF_TEST */
|
84
apps/sam/c/src/strl.c
Normal file
84
apps/sam/c/src/strl.c
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.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 <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||||
|
* full size of dst, not space left). At most siz-1 characters
|
||||||
|
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||||
|
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||||
|
* If retval >= siz, truncation occurred.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
strlcat(char *dst, const char *src, size_t siz)
|
||||||
|
{
|
||||||
|
register char *d = dst;
|
||||||
|
register const char *s = src;
|
||||||
|
register size_t n = siz;
|
||||||
|
size_t dlen;
|
||||||
|
|
||||||
|
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||||
|
while (n-- != 0 && *d != '\0')
|
||||||
|
d++;
|
||||||
|
dlen = d - dst;
|
||||||
|
n = siz - dlen;
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return(dlen + strlen(s));
|
||||||
|
while (*s != '\0') {
|
||||||
|
if (n != 1) {
|
||||||
|
*d++ = *s;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
*d = '\0';
|
||||||
|
|
||||||
|
return(dlen + (s - src)); /* count does not include NUL */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy src to string dst of size siz. At most siz-1 characters
|
||||||
|
* will be copied. Always NUL terminates (unless siz == 0).
|
||||||
|
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
strlcpy(char *dst, const char *src, size_t siz)
|
||||||
|
{
|
||||||
|
register char *d = dst;
|
||||||
|
register const char *s = src;
|
||||||
|
register size_t n = siz;
|
||||||
|
|
||||||
|
/* Copy as many bytes as will fit */
|
||||||
|
if (n != 0 && --n != 0) {
|
||||||
|
do {
|
||||||
|
if ((*d++ = *s++) == 0)
|
||||||
|
break;
|
||||||
|
} while (--n != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||||
|
if (n == 0) {
|
||||||
|
if (siz != 0)
|
||||||
|
*d = '\0'; /* NUL-terminate dst */
|
||||||
|
while (*s++)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(s - src - 1); /* count does not include NUL */
|
||||||
|
}
|
Reference in New Issue
Block a user