mirror of https://github.com/macssh/macssh.git
first import
This commit is contained in:
parent
9b784c8588
commit
5b5e0e778c
|
@ -0,0 +1,13 @@
|
|||
SUBDIRS = . testsuite
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
bin_PROGRAMS = sftp-server
|
||||
noinst_PROGRAMS = sftp-test-client dump-hex
|
||||
|
||||
EXTRA_DIST = buffer.h client.h filemode.h idcache.h sftp.h werror.h xmalloc.h
|
||||
|
||||
sftp_server_SOURCES = sftp-server.c buffer.c filemode.c idcache.c xmalloc.c
|
||||
|
||||
sftp_test_client_SOURCES = sftp-test-client.c buffer.c xmalloc.c werror.c client.c
|
||||
|
|
@ -0,0 +1,479 @@
|
|||
# Makefile.in generated automatically by automake 1.4 from Makefile.am
|
||||
|
||||
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DESTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = .
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
CC = @CC@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
PACKAGE = @PACKAGE@
|
||||
RANLIB = @RANLIB@
|
||||
VERSION = @VERSION@
|
||||
|
||||
SUBDIRS = . testsuite
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
bin_PROGRAMS = sftp-server
|
||||
noinst_PROGRAMS = sftp-test-client dump-hex
|
||||
|
||||
EXTRA_DIST = buffer.h client.h filemode.h idcache.h sftp.h werror.h xmalloc.h
|
||||
|
||||
sftp_server_SOURCES = sftp-server.c buffer.c filemode.c idcache.c xmalloc.c
|
||||
|
||||
sftp_test_client_SOURCES = sftp-test-client.c buffer.c xmalloc.c werror.c client.c
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
|
||||
|
||||
|
||||
DEFS = @DEFS@ -I. -I$(srcdir) -I.
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
sftp_server_OBJECTS = sftp-server.o buffer.o filemode.o idcache.o \
|
||||
xmalloc.o
|
||||
sftp_server_LDADD = $(LDADD)
|
||||
sftp_server_DEPENDENCIES =
|
||||
sftp_server_LDFLAGS =
|
||||
sftp_test_client_OBJECTS = sftp-test-client.o buffer.o xmalloc.o \
|
||||
werror.o client.o
|
||||
sftp_test_client_LDADD = $(LDADD)
|
||||
sftp_test_client_DEPENDENCIES =
|
||||
sftp_test_client_LDFLAGS =
|
||||
dump_hex_SOURCES = dump-hex.c
|
||||
dump_hex_OBJECTS = dump-hex.o
|
||||
dump_hex_LDADD = $(LDADD)
|
||||
dump_hex_DEPENDENCIES =
|
||||
dump_hex_LDFLAGS =
|
||||
CFLAGS = @CFLAGS@
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
DIST_COMMON = ./stamp-h.in Makefile.am Makefile.in acconfig.h \
|
||||
aclocal.m4 config.h.in configure configure.in
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = tar
|
||||
GZIP_ENV = --best
|
||||
SOURCES = $(sftp_server_SOURCES) $(sftp_test_client_SOURCES) dump-hex.c
|
||||
OBJECTS = $(sftp_server_OBJECTS) $(sftp_test_client_OBJECTS) dump-hex.o
|
||||
|
||||
all: all-redirect
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .S .c .o .s
|
||||
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps Makefile
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
$(ACLOCAL_M4): configure.in
|
||||
cd $(srcdir) && $(ACLOCAL)
|
||||
|
||||
config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
$(SHELL) ./config.status --recheck
|
||||
$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
|
||||
cd $(srcdir) && $(AUTOCONF)
|
||||
|
||||
config.h: stamp-h
|
||||
@if test ! -f $@; then \
|
||||
rm -f stamp-h; \
|
||||
$(MAKE) stamp-h; \
|
||||
else :; fi
|
||||
stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES= CONFIG_HEADERS=config.h \
|
||||
$(SHELL) ./config.status
|
||||
@echo timestamp > stamp-h 2> /dev/null
|
||||
$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
|
||||
@if test ! -f $@; then \
|
||||
rm -f $(srcdir)/stamp-h.in; \
|
||||
$(MAKE) $(srcdir)/stamp-h.in; \
|
||||
else :; fi
|
||||
$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
|
||||
cd $(top_srcdir) && $(AUTOHEADER)
|
||||
@echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
|
||||
|
||||
mostlyclean-hdr:
|
||||
|
||||
clean-hdr:
|
||||
|
||||
distclean-hdr:
|
||||
-rm -f config.h
|
||||
|
||||
maintainer-clean-hdr:
|
||||
|
||||
mostlyclean-binPROGRAMS:
|
||||
|
||||
clean-binPROGRAMS:
|
||||
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||
|
||||
distclean-binPROGRAMS:
|
||||
|
||||
maintainer-clean-binPROGRAMS:
|
||||
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
$(mkinstalldirs) $(DESTDIR)$(bindir)
|
||||
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
|
||||
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
|
||||
else :; fi; \
|
||||
done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
|
||||
done
|
||||
|
||||
mostlyclean-noinstPROGRAMS:
|
||||
|
||||
clean-noinstPROGRAMS:
|
||||
-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
|
||||
|
||||
distclean-noinstPROGRAMS:
|
||||
|
||||
maintainer-clean-noinstPROGRAMS:
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.s.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.S.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.o core *.core
|
||||
|
||||
clean-compile:
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
maintainer-clean-compile:
|
||||
|
||||
sftp-server: $(sftp_server_OBJECTS) $(sftp_server_DEPENDENCIES)
|
||||
@rm -f sftp-server
|
||||
$(LINK) $(sftp_server_LDFLAGS) $(sftp_server_OBJECTS) $(sftp_server_LDADD) $(LIBS)
|
||||
|
||||
sftp-test-client: $(sftp_test_client_OBJECTS) $(sftp_test_client_DEPENDENCIES)
|
||||
@rm -f sftp-test-client
|
||||
$(LINK) $(sftp_test_client_LDFLAGS) $(sftp_test_client_OBJECTS) $(sftp_test_client_LDADD) $(LIBS)
|
||||
|
||||
dump-hex: $(dump_hex_OBJECTS) $(dump_hex_DEPENDENCIES)
|
||||
@rm -f dump-hex
|
||||
$(LINK) $(dump_hex_LDFLAGS) $(dump_hex_OBJECTS) $(dump_hex_LDADD) $(LIBS)
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
# To change the values of `make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in `config.status', edit `config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
all-recursive install-data-recursive install-exec-recursive \
|
||||
installdirs-recursive install-recursive uninstall-recursive \
|
||||
check-recursive installcheck-recursive info-recursive dvi-recursive:
|
||||
@set fnord $(MAKEFLAGS); amf=$$2; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
mostlyclean-recursive clean-recursive distclean-recursive \
|
||||
maintainer-clean-recursive:
|
||||
@set fnord $(MAKEFLAGS); amf=$$2; \
|
||||
dot_seen=no; \
|
||||
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
rev="$$subdir $$rev"; \
|
||||
test "$$subdir" = "." && dot_seen=yes; \
|
||||
done; \
|
||||
test "$$dot_seen" = "no" && rev=". $$rev"; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
for subdir in $$rev; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
|
||||
done && test -z "$$fail"
|
||||
tags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
|
||||
done
|
||||
|
||||
tags: TAGS
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP)
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
here=`pwd` && cd $(srcdir) \
|
||||
&& mkid -f$$here/ID $$unique $(LISP)
|
||||
|
||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
|
||||
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
|
||||
|
||||
mostlyclean-tags:
|
||||
|
||||
clean-tags:
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID
|
||||
|
||||
maintainer-clean-tags:
|
||||
|
||||
distdir = $(PACKAGE)-$(VERSION)
|
||||
top_distdir = $(distdir)
|
||||
|
||||
# This target untars the dist file and tries a VPATH configuration. Then
|
||||
# it guarantees that the distribution is self-contained by making another
|
||||
# tarfile.
|
||||
distcheck: dist
|
||||
-rm -rf $(distdir)
|
||||
GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
|
||||
mkdir $(distdir)/=build
|
||||
mkdir $(distdir)/=inst
|
||||
dc_install_base=`cd $(distdir)/=inst && pwd`; \
|
||||
cd $(distdir)/=build \
|
||||
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) check \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) install \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
|
||||
&& $(MAKE) $(AM_MAKEFLAGS) dist
|
||||
-rm -rf $(distdir)
|
||||
@banner="$(distdir).tar.gz is ready for distribution"; \
|
||||
dashes=`echo "$$banner" | sed s/./=/g`; \
|
||||
echo "$$dashes"; \
|
||||
echo "$$banner"; \
|
||||
echo "$$dashes"
|
||||
dist: distdir
|
||||
-chmod -R a+r $(distdir)
|
||||
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
|
||||
-rm -rf $(distdir)
|
||||
dist-all: distdir
|
||||
-chmod -R a+r $(distdir)
|
||||
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
|
||||
-rm -rf $(distdir)
|
||||
distdir: $(DISTFILES)
|
||||
-rm -rf $(distdir)
|
||||
mkdir $(distdir)
|
||||
-chmod 777 $(distdir)
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||
fi; \
|
||||
done
|
||||
for subdir in $(SUBDIRS); do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test -d $(distdir)/$$subdir \
|
||||
|| mkdir $(distdir)/$$subdir \
|
||||
|| exit 1; \
|
||||
chmod 777 $(distdir)/$$subdir; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
buffer.o: buffer.c buffer.h config.h xmalloc.h sftp.h
|
||||
client.o: client.c client.h buffer.h config.h werror.h xmalloc.h sftp.h
|
||||
dump-hex.o: dump-hex.c
|
||||
filemode.o: filemode.c config.h filemode.h
|
||||
idcache.o: idcache.c idcache.h xmalloc.h
|
||||
sftp-server.o: sftp-server.c buffer.h config.h sftp.h filemode.h \
|
||||
idcache.h xmalloc.h
|
||||
sftp-test-client.o: sftp-test-client.c buffer.h config.h sftp.h \
|
||||
xmalloc.h client.h
|
||||
werror.o: werror.c werror.h buffer.h config.h
|
||||
xmalloc.o: xmalloc.c xmalloc.h
|
||||
|
||||
info-am:
|
||||
info: info-recursive
|
||||
dvi-am:
|
||||
dvi: dvi-recursive
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
installcheck-am:
|
||||
installcheck: installcheck-recursive
|
||||
all-recursive-am: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
install-exec: install-exec-recursive
|
||||
|
||||
install-data-am:
|
||||
install-data: install-data-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
install: install-recursive
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
uninstall: uninstall-recursive
|
||||
all-am: Makefile $(PROGRAMS) config.h
|
||||
all-redirect: all-recursive-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
$(mkinstalldirs) $(DESTDIR)$(bindir)
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
|
||||
maintainer-clean-generic:
|
||||
mostlyclean-am: mostlyclean-hdr mostlyclean-binPROGRAMS \
|
||||
mostlyclean-noinstPROGRAMS mostlyclean-compile \
|
||||
mostlyclean-tags mostlyclean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
clean-am: clean-hdr clean-binPROGRAMS clean-noinstPROGRAMS \
|
||||
clean-compile clean-tags clean-generic mostlyclean-am
|
||||
|
||||
clean: clean-recursive
|
||||
|
||||
distclean-am: distclean-hdr distclean-binPROGRAMS \
|
||||
distclean-noinstPROGRAMS distclean-compile \
|
||||
distclean-tags distclean-generic clean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -f config.status
|
||||
|
||||
maintainer-clean-am: maintainer-clean-hdr maintainer-clean-binPROGRAMS \
|
||||
maintainer-clean-noinstPROGRAMS \
|
||||
maintainer-clean-compile maintainer-clean-tags \
|
||||
maintainer-clean-generic distclean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f config.status
|
||||
|
||||
.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
|
||||
mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
|
||||
maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
|
||||
mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \
|
||||
clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS \
|
||||
mostlyclean-compile distclean-compile clean-compile \
|
||||
maintainer-clean-compile install-data-recursive \
|
||||
uninstall-data-recursive install-exec-recursive \
|
||||
uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
|
||||
all-recursive check-recursive installcheck-recursive info-recursive \
|
||||
dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
|
||||
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
|
||||
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
|
||||
dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \
|
||||
install-exec-am install-exec install-data-am install-data install-am \
|
||||
install uninstall-am uninstall all-redirect all-am all installdirs-am \
|
||||
installdirs mostlyclean-generic distclean-generic clean-generic \
|
||||
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
|
@ -0,0 +1,2 @@
|
|||
/* Define if the compiler understands __attribute__ */
|
||||
#undef HAVE_GCC_ATTRIBUTE
|
|
@ -0,0 +1,215 @@
|
|||
dnl aclocal.m4 generated automatically by aclocal 1.4
|
||||
|
||||
dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl This program is distributed in the hope that it will be useful,
|
||||
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
dnl PARTICULAR PURPOSE.
|
||||
|
||||
# Do all the work for Automake. This macro actually does too much --
|
||||
# some checks are only needed if your package does certain things.
|
||||
# But this isn't really a big deal.
|
||||
|
||||
# serial 1
|
||||
|
||||
dnl Usage:
|
||||
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
|
||||
|
||||
AC_DEFUN(AM_INIT_AUTOMAKE,
|
||||
[AC_REQUIRE([AC_PROG_INSTALL])
|
||||
PACKAGE=[$1]
|
||||
AC_SUBST(PACKAGE)
|
||||
VERSION=[$2]
|
||||
AC_SUBST(VERSION)
|
||||
dnl test to see if srcdir already configured
|
||||
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
|
||||
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
|
||||
fi
|
||||
ifelse([$3],,
|
||||
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
|
||||
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
|
||||
AC_REQUIRE([AM_SANITY_CHECK])
|
||||
AC_REQUIRE([AC_ARG_PROGRAM])
|
||||
dnl FIXME This is truly gross.
|
||||
missing_dir=`cd $ac_aux_dir && pwd`
|
||||
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
|
||||
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
|
||||
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
|
||||
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
|
||||
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
|
||||
AC_REQUIRE([AC_PROG_MAKE_SET])])
|
||||
|
||||
#
|
||||
# Check to make sure that the build environment is sane.
|
||||
#
|
||||
|
||||
AC_DEFUN(AM_SANITY_CHECK,
|
||||
[AC_MSG_CHECKING([whether build environment is sane])
|
||||
# Just in case
|
||||
sleep 1
|
||||
echo timestamp > conftestfile
|
||||
# Do `set' in a subshell so we don't clobber the current shell's
|
||||
# arguments. Must try -L first in case configure is actually a
|
||||
# symlink; some systems play weird games with the mod time of symlinks
|
||||
# (eg FreeBSD returns the mod time of the symlink's containing
|
||||
# directory).
|
||||
if (
|
||||
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
|
||||
if test "[$]*" = "X"; then
|
||||
# -L didn't work.
|
||||
set X `ls -t $srcdir/configure conftestfile`
|
||||
fi
|
||||
if test "[$]*" != "X $srcdir/configure conftestfile" \
|
||||
&& test "[$]*" != "X conftestfile $srcdir/configure"; then
|
||||
|
||||
# If neither matched, then we have a broken ls. This can happen
|
||||
# if, for instance, CONFIG_SHELL is bash and it inherits a
|
||||
# broken ls alias from the environment. This has actually
|
||||
# happened. Such a system could not be considered "sane".
|
||||
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
|
||||
alias in your environment])
|
||||
fi
|
||||
|
||||
test "[$]2" = conftestfile
|
||||
)
|
||||
then
|
||||
# Ok.
|
||||
:
|
||||
else
|
||||
AC_MSG_ERROR([newly created file is older than distributed files!
|
||||
Check your system clock])
|
||||
fi
|
||||
rm -f conftest*
|
||||
AC_MSG_RESULT(yes)])
|
||||
|
||||
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
|
||||
dnl The program must properly implement --version.
|
||||
AC_DEFUN(AM_MISSING_PROG,
|
||||
[AC_MSG_CHECKING(for working $2)
|
||||
# Run test in a subshell; some versions of sh will print an error if
|
||||
# an executable is not found, even if stderr is redirected.
|
||||
# Redirect stdin to placate older versions of autoconf. Sigh.
|
||||
if ($2 --version) < /dev/null > /dev/null 2>&1; then
|
||||
$1=$2
|
||||
AC_MSG_RESULT(found)
|
||||
else
|
||||
$1="$3/missing $2"
|
||||
AC_MSG_RESULT(missing)
|
||||
fi
|
||||
AC_SUBST($1)])
|
||||
|
||||
# Like AC_CONFIG_HEADER, but automatically create stamp file.
|
||||
|
||||
AC_DEFUN(AM_CONFIG_HEADER,
|
||||
[AC_PREREQ([2.12])
|
||||
AC_CONFIG_HEADER([$1])
|
||||
dnl When config.status generates a header, we must update the stamp-h file.
|
||||
dnl This file resides in the same directory as the config header
|
||||
dnl that is generated. We must strip everything past the first ":",
|
||||
dnl and everything past the last "/".
|
||||
AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
|
||||
ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
|
||||
<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
|
||||
<<am_indx=1
|
||||
for am_file in <<$1>>; do
|
||||
case " <<$>>CONFIG_HEADERS " in
|
||||
*" <<$>>am_file "*<<)>>
|
||||
echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
|
||||
;;
|
||||
esac
|
||||
am_indx=`expr "<<$>>am_indx" + 1`
|
||||
done<<>>dnl>>)
|
||||
changequote([,]))])
|
||||
|
||||
|
||||
# serial 1
|
||||
|
||||
# @defmac AC_PROG_CC_STDC
|
||||
# @maindex PROG_CC_STDC
|
||||
# @ovindex CC
|
||||
# If the C compiler in not in ANSI C mode by default, try to add an option
|
||||
# to output variable @code{CC} to make it so. This macro tries various
|
||||
# options that select ANSI C on some system or another. It considers the
|
||||
# compiler to be in ANSI C mode if it handles function prototypes correctly.
|
||||
#
|
||||
# If you use this macro, you should check after calling it whether the C
|
||||
# compiler has been set to accept ANSI C; if not, the shell variable
|
||||
# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
|
||||
# code in ANSI C, you can make an un-ANSIfied copy of it by using the
|
||||
# program @code{ansi2knr}, which comes with Ghostscript.
|
||||
# @end defmac
|
||||
|
||||
AC_DEFUN(AM_PROG_CC_STDC,
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_BEFORE([$0], [AC_C_INLINE])
|
||||
AC_BEFORE([$0], [AC_C_CONST])
|
||||
dnl Force this before AC_PROG_CPP. Some cpp's, eg on HPUX, require
|
||||
dnl a magic option to avoid problems with ANSI preprocessor commands
|
||||
dnl like #elif.
|
||||
dnl FIXME: can't do this because then AC_AIX won't work due to a
|
||||
dnl circular dependency.
|
||||
dnl AC_BEFORE([$0], [AC_PROG_CPP])
|
||||
AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
|
||||
AC_CACHE_VAL(am_cv_prog_cc_stdc,
|
||||
[am_cv_prog_cc_stdc=no
|
||||
ac_save_CC="$CC"
|
||||
# Don't try gcc -ansi; that turns off useful extensions and
|
||||
# breaks some systems' header files.
|
||||
# AIX -qlanglvl=ansi
|
||||
# Ultrix and OSF/1 -std1
|
||||
# HP-UX -Aa -D_HPUX_SOURCE
|
||||
# SVR4 -Xc -D__EXTENSIONS__
|
||||
for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
|
||||
do
|
||||
CC="$ac_save_CC $ac_arg"
|
||||
AC_TRY_COMPILE(
|
||||
[#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
|
||||
struct buf { int x; };
|
||||
FILE * (*rcsopen) (struct buf *, struct stat *, int);
|
||||
static char *e (p, i)
|
||||
char **p;
|
||||
int i;
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
static char *f (char * (*g) (char **, int), char **p, ...)
|
||||
{
|
||||
char *s;
|
||||
va_list v;
|
||||
va_start (v,p);
|
||||
s = g (p, va_arg (v,int));
|
||||
va_end (v);
|
||||
return s;
|
||||
}
|
||||
int test (int i, double x);
|
||||
struct s1 {int (*f) (int a);};
|
||||
struct s2 {int (*f) (double a);};
|
||||
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
|
||||
int argc;
|
||||
char **argv;
|
||||
], [
|
||||
return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
|
||||
],
|
||||
[am_cv_prog_cc_stdc="$ac_arg"; break])
|
||||
done
|
||||
CC="$ac_save_CC"
|
||||
])
|
||||
if test -z "$am_cv_prog_cc_stdc"; then
|
||||
AC_MSG_RESULT([none needed])
|
||||
else
|
||||
AC_MSG_RESULT($am_cv_prog_cc_stdc)
|
||||
fi
|
||||
case "x$am_cv_prog_cc_stdc" in
|
||||
x|xno) ;;
|
||||
*) CC="$CC $am_cv_prog_cc_stdc" ;;
|
||||
esac
|
||||
])
|
||||
|
|
@ -0,0 +1,605 @@
|
|||
/* buffer.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Buffering for sftp.
|
||||
*/
|
||||
|
||||
/* lsh, an implementation of the ssh protocol
|
||||
*
|
||||
* Copyright (C) 2001 Niels Möller
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "sftp.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#define FATAL(x) do { fputs("sftp-server: " x "\n", stderr); exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Reads a 32-bit integer, in network byte order */
|
||||
#define READ_UINT32(p) \
|
||||
( (((UINT32) (p)[0]) << 24) \
|
||||
| (((UINT32) (p)[1]) << 16) \
|
||||
| (((UINT32) (p)[2]) << 8) \
|
||||
| ((UINT32) (p)[3]))
|
||||
|
||||
#define WRITE_UINT32(p, i) \
|
||||
do { \
|
||||
(p)[0] = ((i) >> 24) & 0xff; \
|
||||
(p)[1] = ((i) >> 16) & 0xff; \
|
||||
(p)[2] = ((i) >> 8) & 0xff; \
|
||||
(p)[3] = (i) & 0xff; \
|
||||
} while(0)
|
||||
|
||||
#define SFTP_MAX_STRINGS 2
|
||||
|
||||
struct sftp_input
|
||||
{
|
||||
FILE *f;
|
||||
UINT32 left;
|
||||
|
||||
/* Strings that we own */
|
||||
UINT8 *strings[SFTP_MAX_STRINGS];
|
||||
unsigned used_strings;
|
||||
};
|
||||
|
||||
struct sftp_output
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
/* The message type is the first byte of a message, after the
|
||||
* length. */
|
||||
UINT8 msg;
|
||||
|
||||
/* The next word is either the id, or the version. */
|
||||
UINT32 first;
|
||||
|
||||
/* The rest of the packet is variable length. */
|
||||
UINT8 *data;
|
||||
UINT32 size;
|
||||
UINT32 i;
|
||||
};
|
||||
|
||||
/* Input */
|
||||
|
||||
static int
|
||||
sftp_check_input(const struct sftp_input *i, UINT32 length)
|
||||
{
|
||||
return (i->left >= length);
|
||||
}
|
||||
|
||||
int
|
||||
sftp_get_data(struct sftp_input *i, UINT32 length, UINT8 *data)
|
||||
{
|
||||
if (sftp_check_input(i, length))
|
||||
{
|
||||
i->left -= length;
|
||||
return (fread(data, 1, length, i->f) == length);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define GET_DATA(i, buf) \
|
||||
(sftp_get_data((i), sizeof((buf)), (buf)))
|
||||
|
||||
int
|
||||
sftp_get_uint8(struct sftp_input *i, UINT8 *value)
|
||||
{
|
||||
return sftp_get_data(i, 1, value);
|
||||
}
|
||||
|
||||
int
|
||||
sftp_get_uint32(struct sftp_input *i, UINT32 *value)
|
||||
{
|
||||
UINT8 buf[4];
|
||||
if (!GET_DATA(i, buf))
|
||||
return 0;
|
||||
|
||||
*value = READ_UINT32(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
UINT8 *
|
||||
sftp_get_string(struct sftp_input *i, UINT32 *length)
|
||||
{
|
||||
UINT8 *data;
|
||||
|
||||
if (!(sftp_get_uint32(i, length) && sftp_check_input(i, *length)))
|
||||
return NULL;
|
||||
|
||||
data = xmalloc(*length + 1);
|
||||
|
||||
if (!sftp_get_data(i, *length, data))
|
||||
{
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* NUL-terminate, for convenience */
|
||||
data[*length] = '\0';
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void
|
||||
sftp_free_string(UINT8 *s)
|
||||
{
|
||||
free(s);
|
||||
}
|
||||
|
||||
UINT8 *
|
||||
sftp_get_string_auto(struct sftp_input *i, UINT32 *length)
|
||||
{
|
||||
UINT8 *data;
|
||||
|
||||
assert(i->used_strings < SFTP_MAX_STRINGS);
|
||||
|
||||
data = sftp_get_string(i, length);
|
||||
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
/* Remember the string. */
|
||||
i->strings[i->used_strings++] = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
int
|
||||
sftp_get_eod(struct sftp_input *i)
|
||||
{
|
||||
return !i->left;
|
||||
}
|
||||
|
||||
/* Input */
|
||||
struct sftp_input *
|
||||
sftp_make_input(FILE *f)
|
||||
{
|
||||
struct sftp_input *i = xmalloc(sizeof(struct sftp_input));
|
||||
|
||||
i->f = f;
|
||||
i->left = 0;
|
||||
i->used_strings = 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
sftp_input_clear_strings(struct sftp_input *i)
|
||||
{
|
||||
unsigned k;
|
||||
|
||||
for (k = 0; k < i->used_strings; k++)
|
||||
sftp_free_string(i->strings[k]);
|
||||
|
||||
i->used_strings = 0;
|
||||
}
|
||||
|
||||
/* Returns 1 of all was well, 0 on error, and -1 on EOF */
|
||||
int
|
||||
sftp_read_packet(struct sftp_input *i)
|
||||
{
|
||||
UINT8 buf[4];
|
||||
int done;
|
||||
|
||||
if (i->left)
|
||||
return 0;
|
||||
|
||||
/* First, deallocate the strings. */
|
||||
sftp_input_clear_strings(i);
|
||||
|
||||
done = fread(buf, 1, sizeof(buf), i->f);
|
||||
|
||||
switch (done)
|
||||
{
|
||||
case 0:
|
||||
return feof(i->f) ? -1 : 0;
|
||||
case 4:
|
||||
i->left = READ_UINT32(buf);
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Output */
|
||||
|
||||
static void
|
||||
sftp_check_output(struct sftp_output *o, UINT32 length)
|
||||
{
|
||||
UINT32 needed = o->i + length;
|
||||
if (!o->data || (needed > o->size))
|
||||
{
|
||||
UINT32 size = 2 * needed + 40;
|
||||
o->data = xrealloc(o->data, size);
|
||||
|
||||
o->size = size;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sftp_put_data(struct sftp_output *o, UINT32 length, const UINT8 *data)
|
||||
{
|
||||
sftp_check_output(o, length);
|
||||
|
||||
memcpy(o->data + o->i, data, length);
|
||||
o->i += length;
|
||||
}
|
||||
|
||||
#define PUT_DATA(o, buf) \
|
||||
(sftp_put_data((o), sizeof((buf)), (buf)))
|
||||
|
||||
void
|
||||
sftp_put_uint8(struct sftp_output *o, UINT8 value)
|
||||
{
|
||||
sftp_check_output(o, 1);
|
||||
|
||||
o->data[o->i++] = value;
|
||||
}
|
||||
|
||||
void
|
||||
sftp_put_uint32(struct sftp_output *o, UINT32 value)
|
||||
{
|
||||
UINT8 buf[4];
|
||||
|
||||
WRITE_UINT32(buf, value);
|
||||
PUT_DATA(o, buf);
|
||||
}
|
||||
|
||||
void
|
||||
sftp_put_string(struct sftp_output *o, UINT32 length, const UINT8 *data)
|
||||
{
|
||||
sftp_put_uint32(o, length);
|
||||
sftp_put_data(o, length, data);
|
||||
}
|
||||
|
||||
UINT32
|
||||
sftp_put_reserve_length(struct sftp_output *o)
|
||||
{
|
||||
UINT32 index;
|
||||
sftp_check_output(o, 4);
|
||||
|
||||
index = o->i;
|
||||
o->i += 4;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
sftp_put_length(struct sftp_output *o,
|
||||
UINT32 index,
|
||||
UINT32 length)
|
||||
{
|
||||
assert( (index + 4) < o->i);
|
||||
WRITE_UINT32(o->data + index, length);
|
||||
}
|
||||
|
||||
void
|
||||
sftp_put_final_length(struct sftp_output *o,
|
||||
UINT32 index)
|
||||
{
|
||||
sftp_put_length(o, index, o->i - index - 4);
|
||||
}
|
||||
|
||||
void
|
||||
sftp_put_reset(struct sftp_output *o,
|
||||
UINT32 index)
|
||||
{
|
||||
assert(index < o->i);
|
||||
o->i = index;
|
||||
}
|
||||
|
||||
UINT32
|
||||
sftp_put_printf(struct sftp_output *o, const char *format, ...)
|
||||
{
|
||||
/* Initial buffer space */
|
||||
int needed;
|
||||
int length;
|
||||
|
||||
for (needed = 100;; needed *= 2)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
sftp_check_output(o, needed);
|
||||
length = vsnprintf(o->data + o->i, needed, format, args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
if ( (length >= 0) && (length < needed))
|
||||
break;
|
||||
}
|
||||
o->i += length;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/* If SIZE > 0 it is the desired field length, and
|
||||
* smaller output is padded with blanks. */
|
||||
UINT32
|
||||
sftp_put_strftime(struct sftp_output *o, UINT32 size, const char *format,
|
||||
const struct tm *tm)
|
||||
{
|
||||
/* Initial buffer space */
|
||||
size_t needed;
|
||||
size_t length;
|
||||
|
||||
for (needed = size ? size : 100;; needed *= 2)
|
||||
{
|
||||
sftp_check_output(o, needed);
|
||||
length = strftime(o->data + o->i, needed, format, tm);
|
||||
|
||||
if ( (length > 0) && (length < needed))
|
||||
break;
|
||||
}
|
||||
|
||||
while (length < size)
|
||||
o->data[o->i + length++] = ' ';
|
||||
|
||||
o->i += length;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/* 64-bit stuff */
|
||||
#if SIZEOF_OFF_T > 4
|
||||
#define READ_UINT64(p) \
|
||||
( (((UINT64) (p)[0]) << 56) \
|
||||
| (((UINT64) (p)[1]) << 48) \
|
||||
| (((UINT64) (p)[2]) << 40) \
|
||||
| (((UINT64) (p)[3]) << 32) \
|
||||
| (((UINT64) (p)[4]) << 24) \
|
||||
| (((UINT64) (p)[5]) << 16) \
|
||||
| (((UINT64) (p)[6]) << 8) \
|
||||
| ((UINT64) (p)[7]))
|
||||
|
||||
|
||||
int
|
||||
sftp_get_uint64(struct sftp_input *i, off_t *value)
|
||||
{
|
||||
UINT8 buf[8];
|
||||
if (!GET_DATA(i, buf))
|
||||
return 0;
|
||||
|
||||
*value = READ_UINT64(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define WRITE_UINT64(p, i) \
|
||||
do { \
|
||||
(p)[0] = ((i) >> 56) & 0xff; \
|
||||
(p)[1] = ((i) >> 48) & 0xff; \
|
||||
(p)[2] = ((i) >> 40) & 0xff; \
|
||||
(p)[3] = ((i) >> 32) & 0xff; \
|
||||
(p)[4] = ((i) >> 24) & 0xff; \
|
||||
(p)[5] = ((i) >> 16) & 0xff; \
|
||||
(p)[6] = ((i) >> 8) & 0xff; \
|
||||
(p)[7] = (i) & 0xff; \
|
||||
} while(0)
|
||||
|
||||
void
|
||||
sftp_put_uint64(struct sftp_output *o, off_t value)
|
||||
{
|
||||
UINT8 buf[8];
|
||||
|
||||
WRITE_UINT64(buf, value);
|
||||
PUT_DATA(o, buf);
|
||||
}
|
||||
|
||||
#else /* SIZEOF_OFF_T <= 4 */
|
||||
|
||||
/* Fail for too large numbers. */
|
||||
int
|
||||
sftp_get_uint64(struct sftp_input *i, off_t *value)
|
||||
{
|
||||
UINT32 high;
|
||||
UINT32 low;
|
||||
|
||||
if (sftp_get_uint32(i, &high)
|
||||
&& !high
|
||||
&& sftp_get_uint32(i, &low))
|
||||
{
|
||||
*value = low;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
sftp_put_uint64(struct sftp_output *o, off_t value)
|
||||
{
|
||||
sftp_put_uint32(o, 0);
|
||||
sftp_put_uint32(o, value);
|
||||
}
|
||||
|
||||
#endif /* SIZEOF_OFF_T <= 4 */
|
||||
|
||||
/* The first part of the buffer is always
|
||||
*
|
||||
* uint32 length
|
||||
* uint8 msg
|
||||
* uint32 id/version
|
||||
*/
|
||||
|
||||
struct sftp_output *
|
||||
sftp_make_output(FILE *f)
|
||||
{
|
||||
struct sftp_output *o = xmalloc(sizeof(struct sftp_output));
|
||||
|
||||
o->f = f;
|
||||
o->data = NULL;
|
||||
o->size = 0;
|
||||
o->i = 0;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
void
|
||||
sftp_set_msg(struct sftp_output *o, UINT8 msg)
|
||||
{
|
||||
o->msg = msg;
|
||||
}
|
||||
|
||||
void
|
||||
sftp_set_id(struct sftp_output *o, UINT32 id)
|
||||
{
|
||||
o->first = id;
|
||||
}
|
||||
|
||||
int
|
||||
sftp_write_packet(struct sftp_output *o)
|
||||
{
|
||||
UINT32 length = o->i + 5;
|
||||
UINT8 buf[9];
|
||||
|
||||
WRITE_UINT32(buf, length);
|
||||
buf[4] = o->msg;
|
||||
WRITE_UINT32(buf + 5, o->first);
|
||||
|
||||
if (fwrite(buf, 1, 9, o->f) != 9)
|
||||
return 0;
|
||||
if (fwrite(o->data, 1, o->i, o->f) != o->i)
|
||||
return 0;
|
||||
|
||||
o->i = 0;
|
||||
|
||||
/* FIXME: Flushing after each packet is sub-optimal. */
|
||||
if (fflush(o->f))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* General functions */
|
||||
|
||||
void
|
||||
sftp_clear_attrib(struct sftp_attrib *a)
|
||||
{
|
||||
a->flags = 0;
|
||||
a->size = 0;
|
||||
a->uid = 0;
|
||||
a->gid = 0;
|
||||
a->permissions = 0;
|
||||
a->atime = 0;
|
||||
a->mtime = 0;
|
||||
};
|
||||
|
||||
int
|
||||
sftp_skip_extension(struct sftp_input *i)
|
||||
{
|
||||
UINT32 length;
|
||||
UINT8 *data;
|
||||
unsigned j;
|
||||
|
||||
/* Skip name and value*/
|
||||
for (j = 0; j<2; j++)
|
||||
{
|
||||
if (!(data = sftp_get_string(i, &length)))
|
||||
return 0;
|
||||
}
|
||||
sftp_input_clear_strings(i);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
sftp_get_attrib(struct sftp_input *i, struct sftp_attrib *a)
|
||||
{
|
||||
sftp_clear_attrib(a);
|
||||
|
||||
if (!sftp_get_uint32(i, &a->flags))
|
||||
return 0;
|
||||
|
||||
if (a->flags & SSH_FILEXFER_ATTR_SIZE)
|
||||
{
|
||||
if (!sftp_get_uint64(i, &a->size))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a->flags & SSH_FILEXFER_ATTR_UIDGID)
|
||||
{
|
||||
if (!sftp_get_uint32(i, &a->uid))
|
||||
return 0;
|
||||
|
||||
if (!sftp_get_uint32(i, &a->gid))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a->flags & SSH_FILEXFER_ATTR_PERMISSIONS)
|
||||
{
|
||||
if (!sftp_get_uint32(i, &a->permissions))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a->flags & SSH_FILEXFER_ATTR_ACMODTIME)
|
||||
{
|
||||
if (!sftp_get_uint32(i, &a->atime))
|
||||
return 0;
|
||||
|
||||
if (!sftp_get_uint32(i, &a->mtime))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a->flags & SSH_FILEXFER_ATTR_EXTENDED)
|
||||
{
|
||||
UINT32 count;
|
||||
UINT32 n;
|
||||
|
||||
if (!sftp_get_uint32(i, &count))
|
||||
return 0;
|
||||
|
||||
/* Just skip the extensions */
|
||||
for (n = 0; n < count; n++)
|
||||
if (!sftp_skip_extension(i))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
sftp_put_attrib(struct sftp_output *o, const struct sftp_attrib *a)
|
||||
{
|
||||
assert(!(a->flags & SSH_FILEXFER_ATTR_EXTENDED));
|
||||
|
||||
sftp_put_uint32(o, a->flags);
|
||||
|
||||
if (a->flags & SSH_FILEXFER_ATTR_SIZE)
|
||||
sftp_put_uint64(o, a->size);
|
||||
|
||||
if (a->flags & SSH_FILEXFER_ATTR_UIDGID)
|
||||
{
|
||||
sftp_put_uint32(o, a->uid);
|
||||
sftp_put_uint32(o, a->gid);
|
||||
}
|
||||
|
||||
if (a->flags & SSH_FILEXFER_ATTR_PERMISSIONS)
|
||||
sftp_put_uint32(o, a->permissions);
|
||||
|
||||
if (a->flags & SSH_FILEXFER_ATTR_ACMODTIME)
|
||||
{
|
||||
sftp_put_uint32(o, a->atime);
|
||||
sftp_put_uint32(o, a->mtime);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
/* buffer.h
|
||||
*
|
||||
* Buffering for sftp.
|
||||
*/
|
||||
|
||||
/* lsh, an implementation of the ssh protocol
|
||||
*
|
||||
* Copyright (C) 2001 Niels Möller
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef SFTP_BUFFER_H_INCLUDED
|
||||
#define SFTP_BUFFER_H_INCLUDED
|
||||
|
||||
/* Basic configuration */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* For off_t */
|
||||
#include <sys/types.h>
|
||||
|
||||
#if SIZEOF_SHORT >= 4
|
||||
# define UINT32 unsigned short
|
||||
#elif SIZEOF_INT >= 4
|
||||
# define UINT32 unsigned int
|
||||
#elif SIZEOF_LONG >= 4
|
||||
# define UINT32 unsigned long
|
||||
#else
|
||||
# error No suitable type found to use for UINT32
|
||||
#endif /* UINT32 */
|
||||
|
||||
#if SIZEOF_SHORT >= 2
|
||||
# define UINT16 unsigned short
|
||||
#elif SIZEOF_INT >= 2
|
||||
# define UINT16 unsigned int
|
||||
#else
|
||||
# error No suitable type found to use for UINT16
|
||||
#endif /* UINT16 */
|
||||
|
||||
#define UINT8 unsigned char
|
||||
|
||||
#if __GNUC__ && HAVE_GCC_ATTRIBUTE
|
||||
# define NORETURN __attribute__ ((__noreturn__))
|
||||
# define PRINTF_STYLE(f, a) __attribute__ ((__format__ (__printf__, f, a)))
|
||||
# define UNUSED __attribute__ ((__unused__))
|
||||
#else
|
||||
# define NORETURN
|
||||
# define PRINTF_STYLE(f, a)
|
||||
# define UNUSED
|
||||
#endif
|
||||
|
||||
|
||||
/* Abstract input and output functions */
|
||||
#include <time.h>
|
||||
|
||||
struct sftp_input;
|
||||
struct sftp_output;
|
||||
|
||||
/* Input */
|
||||
|
||||
/* Returns 1 of all was well, 0 on error, and -1 on EOF */
|
||||
int
|
||||
sftp_read_packet(struct sftp_input *i);
|
||||
|
||||
int
|
||||
sftp_get_data(struct sftp_input *i, UINT32 length, UINT8 *data);
|
||||
|
||||
int
|
||||
sftp_get_uint8(struct sftp_input *i, UINT8 *value);
|
||||
|
||||
int
|
||||
sftp_get_uint32(struct sftp_input *i, UINT32 *value);
|
||||
|
||||
int
|
||||
sftp_get_uint64(struct sftp_input *i, off_t *value);
|
||||
|
||||
/* Allocates storage. Caller must deallocate using
|
||||
* sftp_free_string. */
|
||||
UINT8 *
|
||||
sftp_get_string(struct sftp_input *i, UINT32 *length);
|
||||
|
||||
void
|
||||
sftp_free_string(UINT8 *s);
|
||||
|
||||
/* Like sftp_get_string, but the data is deallocated automatically by
|
||||
* sftp_read_packet and sftp_input_clear_strings. */
|
||||
UINT8 *
|
||||
sftp_get_string_auto(struct sftp_input *i, UINT32 *length);
|
||||
|
||||
void
|
||||
sftp_input_clear_strings(struct sftp_input *i);
|
||||
|
||||
int
|
||||
sftp_get_eod(struct sftp_input *i);
|
||||
|
||||
/* Output */
|
||||
|
||||
void
|
||||
sftp_set_msg(struct sftp_output *o, UINT8 msg);
|
||||
|
||||
void
|
||||
sftp_set_id(struct sftp_output *o, UINT32 id);
|
||||
|
||||
int
|
||||
sftp_write_packet(struct sftp_output *o);
|
||||
|
||||
void
|
||||
sftp_put_data(struct sftp_output *o, UINT32 length, const UINT8 *data);
|
||||
|
||||
void
|
||||
sftp_put_uint8(struct sftp_output *o, UINT8 value);
|
||||
|
||||
void
|
||||
sftp_put_uint32(struct sftp_output *o, UINT32 value);
|
||||
|
||||
void
|
||||
sftp_put_uint64(struct sftp_output *o, off_t value);
|
||||
|
||||
void
|
||||
sftp_put_string(struct sftp_output *o, UINT32 length, const UINT8 *data);
|
||||
|
||||
/* Returns index. */
|
||||
UINT32
|
||||
sftp_put_reserve_length(struct sftp_output *o);
|
||||
|
||||
void
|
||||
sftp_put_final_length(struct sftp_output *o,
|
||||
UINT32 index);
|
||||
|
||||
void
|
||||
sftp_put_length(struct sftp_output *o,
|
||||
UINT32 index,
|
||||
UINT32 length);
|
||||
|
||||
void
|
||||
sftp_put_reset(struct sftp_output *o,
|
||||
UINT32 index);
|
||||
|
||||
UINT32
|
||||
sftp_put_printf(struct sftp_output *o, const char *format, ...)
|
||||
PRINTF_STYLE(2,3);
|
||||
|
||||
UINT32
|
||||
sftp_put_strftime(struct sftp_output *o, UINT32 size,
|
||||
const char *format,
|
||||
const struct tm *tm);
|
||||
|
||||
|
||||
/* Constructed types. */
|
||||
|
||||
struct sftp_attrib
|
||||
{
|
||||
UINT32 flags;
|
||||
off_t size;
|
||||
UINT32 uid;
|
||||
UINT32 gid;
|
||||
UINT32 permissions;
|
||||
|
||||
/* NOTE: The representations of times is about to change. */
|
||||
UINT32 atime;
|
||||
UINT32 mtime;
|
||||
};
|
||||
|
||||
void
|
||||
sftp_clear_attrib(struct sftp_attrib *a);
|
||||
|
||||
int
|
||||
sftp_get_attrib(struct sftp_input *i, struct sftp_attrib *a);
|
||||
|
||||
void
|
||||
sftp_put_attrib(struct sftp_output *o, const struct sftp_attrib *a);
|
||||
|
||||
int
|
||||
sftp_skip_extension(struct sftp_input *i);
|
||||
|
||||
|
||||
/* Simple input and output objects based on FILE * */
|
||||
#include <stdio.h>
|
||||
|
||||
struct sftp_input *
|
||||
sftp_make_input(FILE *f);
|
||||
|
||||
struct sftp_output *
|
||||
sftp_make_output(FILE *f);
|
||||
|
||||
|
||||
#endif /* SFTP_BUFFER_H_INCLUDED */
|
|
@ -0,0 +1,154 @@
|
|||
/* client.c
|
||||
*
|
||||
* Utility functions for the client side of the protocol.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/* lsh, an implementation of the ssh protocol
|
||||
*
|
||||
* Copyright (C) 2001 Niels Möller
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "client.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include "werror.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#include "sftp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* We never have several pending calls at once. */
|
||||
static UINT32
|
||||
sftp_client_new_id(void)
|
||||
{ return 17; }
|
||||
|
||||
static struct client_handle *
|
||||
client_get_handle(struct sftp_input *i)
|
||||
{
|
||||
UINT32 length;
|
||||
UINT8 *data;
|
||||
struct client_handle *handle;
|
||||
|
||||
data = sftp_get_string(i, &length);
|
||||
if (!data)
|
||||
fatal("Protocol error, client_get_handle");
|
||||
|
||||
handle = xmalloc(sizeof(*handle));
|
||||
handle->length = length;
|
||||
handle->data = data;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
static UINT8
|
||||
client_get_msg(struct client_ctx *ctx, UINT32 expected)
|
||||
{
|
||||
UINT8 msg;
|
||||
UINT32 id;
|
||||
|
||||
if (sftp_get_uint8(ctx->i, &msg)
|
||||
&& sftp_get_uint32(ctx->i, &id)
|
||||
&& (expected == id))
|
||||
return msg;
|
||||
|
||||
else
|
||||
fatal("Protocol error, client_get_msg");
|
||||
}
|
||||
|
||||
static UINT32
|
||||
client_get_status(struct client_ctx *ctx, UINT32 id)
|
||||
{
|
||||
UINT32 status;
|
||||
|
||||
if ( (client_get_msg(ctx, id) == SSH_FXP_STATUS)
|
||||
&& sftp_get_uint32(ctx->i, &status))
|
||||
return status;
|
||||
|
||||
else
|
||||
fatal("Protocol error, client_get_status");
|
||||
}
|
||||
|
||||
static void
|
||||
client_put_handle(struct client_ctx *ctx, struct client_handle *handle)
|
||||
{
|
||||
sftp_put_string(ctx->o, handle->length, handle->data);
|
||||
}
|
||||
|
||||
/* Creates a file handle */
|
||||
struct client_handle *
|
||||
sftp_open(struct client_ctx *ctx,
|
||||
const char *name,
|
||||
UINT32 flags,
|
||||
const struct sftp_attrib *a)
|
||||
{
|
||||
UINT8 msg;
|
||||
UINT32 id = sftp_client_new_id();
|
||||
|
||||
/* Send a OPEN message */
|
||||
sftp_set_msg(ctx->o, SSH_FXP_OPEN);
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, strlen(name), name );
|
||||
sftp_put_uint32(ctx->o, flags);
|
||||
sftp_put_attrib(ctx->o, a);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
msg = client_get_msg(ctx, id);
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case SSH_FXP_HANDLE:
|
||||
return client_get_handle(ctx->i);
|
||||
case SSH_FXP_STATUS:
|
||||
if (!sftp_get_uint32(ctx->i, &ctx->status))
|
||||
fatal("Protocol error, sftp_open");
|
||||
return NULL;
|
||||
default:
|
||||
fatal("Unexpected message from server.");
|
||||
}
|
||||
}
|
||||
|
||||
/* Destroys a file or directory handle */
|
||||
int
|
||||
sftp_close(struct client_ctx *ctx,
|
||||
struct client_handle *handle)
|
||||
{
|
||||
UINT32 id = sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_CLOSE); /* Send a close message */
|
||||
sftp_set_id(ctx->o, id);
|
||||
client_put_handle(ctx, handle);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
/* None of these may fail */
|
||||
ctx->status = client_get_status(ctx, id);
|
||||
|
||||
return (ctx->status == SSH_FX_OK);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/* client.h
|
||||
*
|
||||
* Utility functions for the client side of the protocol.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/* lsh, an implementation of the ssh protocol
|
||||
*
|
||||
* Copyright (C) 2001 Niels Möller
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef SFTP_CLIENT_H_INCLUDED
|
||||
#define SFTP_CLIENT_H_INCLUDED
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
struct client_ctx
|
||||
{
|
||||
struct sftp_input *i;
|
||||
struct sftp_output *o;
|
||||
|
||||
/* Status from latest message. */
|
||||
UINT32 status;
|
||||
};
|
||||
|
||||
/* Handles are strings, choosen by the server. */
|
||||
struct client_handle
|
||||
{
|
||||
UINT32 length;
|
||||
UINT8 *data;
|
||||
};
|
||||
|
||||
/* Creates a file handle */
|
||||
struct client_handle *
|
||||
sftp_open(struct client_ctx *ctx,
|
||||
const char *name,
|
||||
UINT32 flags,
|
||||
const struct sftp_attrib *a);
|
||||
|
||||
/* Destroys a file or directory handle */
|
||||
int
|
||||
sftp_close(struct client_ctx *ctx,
|
||||
struct client_handle *handle);
|
||||
|
||||
|
||||
#endif /* SFTP_CLIENT_H_INCLUDED */
|
|
@ -0,0 +1,67 @@
|
|||
/* config.h.in. Generated automatically from configure.in by autoheader. */
|
||||
/* Define if the compiler understands __attribute__ */
|
||||
#undef HAVE_GCC_ATTRIBUTE
|
||||
|
||||
/* Define if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define if you have the `pread' function. */
|
||||
#undef HAVE_PREAD
|
||||
|
||||
/* Define if you have the `pwrite' function. */
|
||||
#undef HAVE_PWRITE
|
||||
|
||||
/* Define if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* The size of a `int', as computed by sizeof. */
|
||||
#undef SIZEOF_INT
|
||||
|
||||
/* The size of a `long', as computed by sizeof. */
|
||||
#undef SIZEOF_LONG
|
||||
|
||||
/* The size of a `off_t', as computed by sizeof. */
|
||||
#undef SIZEOF_OFF_T
|
||||
|
||||
/* The size of a `short', as computed by sizeof. */
|
||||
#undef SIZEOF_SHORT
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#undef TIME_WITH_SYS_TIME
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef gid_t
|
||||
|
||||
/* Define as `__inline' if that's what the C compiler calls it, or to nothing
|
||||
if it is not supported. */
|
||||
#undef inline
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef uid_t
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,74 @@
|
|||
dnl -*- mode: shell-script; sh-indentation: 2; -*-
|
||||
dnl $Id$
|
||||
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(sftp-server.c)
|
||||
|
||||
AM_INIT_AUTOMAKE(lsh-sftp, 1.0)
|
||||
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_RANLIB
|
||||
AM_PROG_CC_STDC
|
||||
|
||||
if test "x$am_cv_prog_cc_stdc" = xno ; then
|
||||
AC_ERROR([the C compiler doesn't handle ANSI-C])
|
||||
fi
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_TYPE_UID_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_HEADER_TIME
|
||||
|
||||
AC_CHECK_SIZEOF(short, 2)
|
||||
AC_CHECK_SIZEOF(int, 4)
|
||||
AC_CHECK_SIZEOF(long, 4)
|
||||
AC_CHECK_SIZEOF(off_t, 8,
|
||||
[#include <stdio.h>
|
||||
#include <unistd.h>])
|
||||
|
||||
dnl Check for gcc's __attribute__ construction
|
||||
AC_CACHE_CHECK(for __attribute__,
|
||||
lsh_cv_c_attribute,
|
||||
[ AC_TRY_COMPILE([
|
||||
#include <stdlib.h>
|
||||
],
|
||||
[
|
||||
static void foo(void) __attribute__ ((noreturn));
|
||||
|
||||
static void __attribute__ ((noreturn))
|
||||
foo(void)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
],
|
||||
lsh_cv_c_attribute=yes,
|
||||
lsh_cv_c_attribute=no)])
|
||||
|
||||
if test "x$lsh_cv_c_attribute" = "xyes"; then
|
||||
AC_DEFINE(HAVE_GCC_ATTRIBUTE)
|
||||
fi
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_CHECK_FUNCS(pread pwrite)
|
||||
|
||||
# Set these flags *last*, or else the test programs won't compile
|
||||
if test x$GCC = xyes ; then
|
||||
CFLAGS="$CFLAGS -ggdb3 -Wall -W \
|
||||
-Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes \
|
||||
-Waggregate-return \
|
||||
-Wpointer-arith -Wbad-function-cast -Wnested-externs -Wcast-align"
|
||||
fi
|
||||
|
||||
AC_OUTPUT([Makefile testsuite/Makefile])
|
|
@ -0,0 +1,212 @@
|
|||
/* dump-hex.c
|
||||
*
|
||||
* This program copies data from stdin to stdout, and also
|
||||
* writes a hex dump to stderr.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: dump-hex\n"
|
||||
" or dump-hex LABEL\n"
|
||||
" or dump-hex --help\n\n"
|
||||
"Copies data from stdin to stdout,\n"
|
||||
"and also writes a hex dump to stderr.\n");
|
||||
}
|
||||
|
||||
static int is_help_option(const char *arg)
|
||||
{
|
||||
return !strcmp(arg, "-?") || !strcasecmp(arg, "--help");
|
||||
}
|
||||
|
||||
/* Blocks for at least one character, but no longer. Returns number of
|
||||
* characters, just like read. */
|
||||
static int
|
||||
do_read(int fd, char *data, int length)
|
||||
{
|
||||
int res;
|
||||
do
|
||||
res = read(fd, data, length);
|
||||
while ( (res < 0) && (errno == EINTR) );
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
/* Writes all data, unless some error occurs. */
|
||||
static int
|
||||
do_write(int fd, const char *data, int length)
|
||||
{
|
||||
int done;
|
||||
for (done = 0; done < length; )
|
||||
{
|
||||
int res = write(fd, data + done, length - done);
|
||||
if (res < 0)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
done += res;
|
||||
}
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
#define LINE 16
|
||||
|
||||
static int
|
||||
output_line(int fd, const char *label,
|
||||
unsigned pos, const char *data, unsigned length)
|
||||
{
|
||||
/* The format used:
|
||||
*
|
||||
* LABEL ADDRESS DATA ASCII
|
||||
* foobar: 000000B0 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff xxxxxxxxxxxxxxxx
|
||||
*
|
||||
* 0 1 2 3 4 5 6 7
|
||||
* 0123456789012345678901234567890123456789012345678901234567890123456789012
|
||||
*
|
||||
* Lines are 72 characters + the size of the label + newline.
|
||||
*/
|
||||
|
||||
const char hex_digit[16] = "0123456789abcdef";
|
||||
|
||||
unsigned label_length = strlen(label);
|
||||
char *line = alloca(label_length + 80);
|
||||
unsigned i = 0;
|
||||
|
||||
unsigned offset = pos % LINE;
|
||||
unsigned address = pos - offset;
|
||||
|
||||
if (label_length)
|
||||
{
|
||||
/* Non-empty-label */
|
||||
memcpy(line, label, label_length);
|
||||
i = label_length;
|
||||
line[i++] = ':';
|
||||
line[i++] = ' ';
|
||||
}
|
||||
|
||||
/* Write the address field. */
|
||||
{
|
||||
unsigned k;
|
||||
unsigned buffer;
|
||||
|
||||
for (k = 8, buffer = address; k-- > 0; buffer >>= 4)
|
||||
line[i+k] = hex_digit[buffer & 0xf];
|
||||
|
||||
i += 8;
|
||||
}
|
||||
line[i++] = ' ';
|
||||
|
||||
/* Skip to the start of the data */
|
||||
memset(line + i, ' ', 3 * offset);
|
||||
i += 3 * offset;
|
||||
|
||||
/* Write the hex data */
|
||||
{
|
||||
unsigned k;
|
||||
for (k = 0; k<length; k++)
|
||||
{
|
||||
unsigned char c = data[k];
|
||||
line[i++] = hex_digit[c >> 4];
|
||||
line[i++] = hex_digit[c & 0xf];
|
||||
line[i++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip to ascii part */
|
||||
{
|
||||
/* (LINE - (length + offset)) * 3 + offset
|
||||
* = (LINE - length) * 3 - offset * 2
|
||||
*/
|
||||
unsigned skip = 3* (LINE - length) - 2 * offset;
|
||||
memset(line + i, ' ', skip);
|
||||
i += skip;
|
||||
}
|
||||
|
||||
/* Output ascii */
|
||||
{
|
||||
unsigned k;
|
||||
for (k = 0; k<length; k++)
|
||||
{
|
||||
unsigned char c = data[k];
|
||||
line[i++] = isprint(c) ? c : '.';
|
||||
}
|
||||
}
|
||||
|
||||
/* Final newline */
|
||||
line[i++] = '\n';
|
||||
|
||||
return do_write(fd, line, i);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *label;
|
||||
unsigned pos;
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
case 1:
|
||||
label = "";
|
||||
break;
|
||||
case 2:
|
||||
if (is_help_option(argv[1]))
|
||||
{
|
||||
usage();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else label = argv[1];
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for (pos = 0;;)
|
||||
{
|
||||
unsigned char buf[LINE];
|
||||
|
||||
unsigned left = LINE - (pos % LINE);
|
||||
int res;
|
||||
|
||||
/* Try reading the rest of the current line. */
|
||||
res = do_read(STDIN_FILENO, buf, left);
|
||||
if (!res)
|
||||
/* EOF */
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
else if (res < 0)
|
||||
{
|
||||
fprintf(stderr, "%s: read error: %s\n", label, strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Dump it */
|
||||
if (output_line(STDERR_FILENO, label, pos, buf, res) <= 0)
|
||||
{
|
||||
fprintf(stderr, "%s: write error on stderr: %s\n", label, strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* And pass it on */
|
||||
if (do_write(STDOUT_FILENO, buf, res) < 0)
|
||||
{
|
||||
fprintf(stderr, "%s: write error: %s\n", label, strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
pos += res;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,260 @@
|
|||
/* filemode.c -- make a string describing file modes
|
||||
Copyright (C) 1985, 1990, 1993, 1998 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "filemode.h"
|
||||
|
||||
#if !S_IRUSR
|
||||
# if S_IREAD
|
||||
# define S_IRUSR S_IREAD
|
||||
# else
|
||||
# define S_IRUSR 00400
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !S_IWUSR
|
||||
# if S_IWRITE
|
||||
# define S_IWUSR S_IWRITE
|
||||
# else
|
||||
# define S_IWUSR 00200
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !S_IXUSR
|
||||
# if S_IEXEC
|
||||
# define S_IXUSR S_IEXEC
|
||||
# else
|
||||
# define S_IXUSR 00100
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef STAT_MACROS_BROKEN
|
||||
# undef S_ISBLK
|
||||
# undef S_ISCHR
|
||||
# undef S_ISDIR
|
||||
# undef S_ISFIFO
|
||||
# undef S_ISLNK
|
||||
# undef S_ISMPB
|
||||
# undef S_ISMPC
|
||||
# undef S_ISNWK
|
||||
# undef S_ISREG
|
||||
# undef S_ISSOCK
|
||||
#endif /* STAT_MACROS_BROKEN. */
|
||||
|
||||
#if !defined(S_ISBLK) && defined(S_IFBLK)
|
||||
# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
||||
#endif
|
||||
#if !defined(S_ISCHR) && defined(S_IFCHR)
|
||||
# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
#endif
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#if !defined(S_ISREG) && defined(S_IFREG)
|
||||
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#endif
|
||||
#if !defined(S_ISFIFO) && defined(S_IFIFO)
|
||||
# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
#endif
|
||||
#if !defined(S_ISLNK) && defined(S_IFLNK)
|
||||
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
|
||||
# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
|
||||
#endif
|
||||
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
|
||||
# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
|
||||
# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
|
||||
#endif
|
||||
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
|
||||
# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
|
||||
#endif
|
||||
|
||||
/* Look at read, write, and execute bits in BITS and set
|
||||
flags in CHARS accordingly. */
|
||||
|
||||
static void
|
||||
rwx (short unsigned int bits, char *chars)
|
||||
{
|
||||
chars[0] = (bits & S_IRUSR) ? 'r' : '-';
|
||||
chars[1] = (bits & S_IWUSR) ? 'w' : '-';
|
||||
chars[2] = (bits & S_IXUSR) ? 'x' : '-';
|
||||
}
|
||||
|
||||
/* Set the 's' and 't' flags in file attributes string CHARS,
|
||||
according to the file mode BITS. */
|
||||
|
||||
static void
|
||||
setst (short unsigned int bits, char *chars)
|
||||
{
|
||||
#ifdef S_ISUID
|
||||
if (bits & S_ISUID)
|
||||
{
|
||||
if (chars[3] != 'x')
|
||||
/* Set-uid, but not executable by owner. */
|
||||
chars[3] = 'S';
|
||||
else
|
||||
chars[3] = 's';
|
||||
}
|
||||
#endif
|
||||
#ifdef S_ISGID
|
||||
if (bits & S_ISGID)
|
||||
{
|
||||
if (chars[6] != 'x')
|
||||
/* Set-gid, but not executable by group. */
|
||||
chars[6] = 'S';
|
||||
else
|
||||
chars[6] = 's';
|
||||
}
|
||||
#endif
|
||||
#ifdef S_ISVTX
|
||||
if (bits & S_ISVTX)
|
||||
{
|
||||
if (chars[9] != 'x')
|
||||
/* Sticky, but not executable by others. */
|
||||
chars[9] = 'T';
|
||||
else
|
||||
chars[9] = 't';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return a character indicating the type of file described by
|
||||
file mode BITS:
|
||||
'd' for directories
|
||||
'b' for block special files
|
||||
'c' for character special files
|
||||
'm' for multiplexor files
|
||||
'M' for an off-line (regular) file
|
||||
'l' for symbolic links
|
||||
's' for sockets
|
||||
'p' for fifos
|
||||
'-' for regular files
|
||||
'?' for any other file type. */
|
||||
|
||||
static char
|
||||
ftypelet (long int bits)
|
||||
{
|
||||
#ifdef S_ISBLK
|
||||
if (S_ISBLK (bits))
|
||||
return 'b';
|
||||
#endif
|
||||
if (S_ISCHR (bits))
|
||||
return 'c';
|
||||
if (S_ISDIR (bits))
|
||||
return 'd';
|
||||
if (S_ISREG (bits))
|
||||
return '-';
|
||||
#ifdef S_ISFIFO
|
||||
if (S_ISFIFO (bits))
|
||||
return 'p';
|
||||
#endif
|
||||
#ifdef S_ISLNK
|
||||
if (S_ISLNK (bits))
|
||||
return 'l';
|
||||
#endif
|
||||
#ifdef S_ISSOCK
|
||||
if (S_ISSOCK (bits))
|
||||
return 's';
|
||||
#endif
|
||||
#ifdef S_ISMPC
|
||||
if (S_ISMPC (bits))
|
||||
return 'm';
|
||||
#endif
|
||||
#ifdef S_ISNWK
|
||||
if (S_ISNWK (bits))
|
||||
return 'n';
|
||||
#endif
|
||||
|
||||
/* The following two tests are for Cray DMF (Data Migration
|
||||
Facility), which is a HSM file system. A migrated file has a
|
||||
`st_dm_mode' that is different from the normal `st_mode', so any
|
||||
tests for migrated files should use the former. */
|
||||
|
||||
#ifdef S_ISOFD
|
||||
if (S_ISOFD (bits))
|
||||
/* off line, with data */
|
||||
return 'M';
|
||||
#endif
|
||||
#ifdef S_ISOFL
|
||||
/* off line, with no data */
|
||||
if (S_ISOFL (bits))
|
||||
return 'M';
|
||||
#endif
|
||||
return '?';
|
||||
}
|
||||
|
||||
/* Like filemodestring, but only the relevant part of the `struct stat'
|
||||
is given as an argument. */
|
||||
|
||||
void
|
||||
mode_string (short unsigned int mode, char *str)
|
||||
{
|
||||
str[0] = ftypelet ((long) mode);
|
||||
rwx ((mode & 0700) << 0, &str[1]);
|
||||
rwx ((mode & 0070) << 3, &str[4]);
|
||||
rwx ((mode & 0007) << 6, &str[7]);
|
||||
setst (mode, str);
|
||||
}
|
||||
|
||||
/* filemodestring - fill in string STR with an ls-style ASCII
|
||||
representation of the st_mode field of file stats block STATP.
|
||||
10 characters are stored in STR; no terminating null is added.
|
||||
The characters stored in STR are:
|
||||
|
||||
0 File type. 'd' for directory, 'c' for character
|
||||
special, 'b' for block special, 'm' for multiplex,
|
||||
'l' for symbolic link, 's' for socket, 'p' for fifo,
|
||||
'-' for regular, '?' for any other file type
|
||||
|
||||
1 'r' if the owner may read, '-' otherwise.
|
||||
|
||||
2 'w' if the owner may write, '-' otherwise.
|
||||
|
||||
3 'x' if the owner may execute, 's' if the file is
|
||||
set-user-id, '-' otherwise.
|
||||
'S' if the file is set-user-id, but the execute
|
||||
bit isn't set.
|
||||
|
||||
4 'r' if group members may read, '-' otherwise.
|
||||
|
||||
5 'w' if group members may write, '-' otherwise.
|
||||
|
||||
6 'x' if group members may execute, 's' if the file is
|
||||
set-group-id, '-' otherwise.
|
||||
'S' if it is set-group-id but not executable.
|
||||
|
||||
7 'r' if any user may read, '-' otherwise.
|
||||
|
||||
8 'w' if any user may write, '-' otherwise.
|
||||
|
||||
9 'x' if any user may execute, 't' if the file is "sticky"
|
||||
(will be retained in swap space after execution), '-'
|
||||
otherwise.
|
||||
'T' if the file is sticky but not executable. */
|
||||
|
||||
void
|
||||
filemodestring (struct stat *statp, char *str)
|
||||
{
|
||||
mode_string (statp->st_mode, str);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef PARAMS
|
||||
# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
||||
# define PARAMS(Args) Args
|
||||
# else
|
||||
# define PARAMS(Args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define MODE_STRING_LENGTH 10
|
||||
void mode_string PARAMS ((short unsigned int mode, char *str));
|
||||
void filemodestring PARAMS ((struct stat *statp, char *str));
|
|
@ -0,0 +1,88 @@
|
|||
/* idcache.c -- map user and group IDs, cached for speed
|
||||
*
|
||||
*/
|
||||
|
||||
/* lsh, an implementation of the ssh protocol
|
||||
*
|
||||
* Copyright (C) 2001 Niels Möller
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "idcache.h"
|
||||
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* For cached user and group info */
|
||||
struct sftp_user_info
|
||||
{
|
||||
int id;
|
||||
const char *name;
|
||||
struct sftp_user_info *next;
|
||||
};
|
||||
|
||||
|
||||
#if 1
|
||||
int
|
||||
sftp_cache_assoc(struct sftp_user_info **cache,
|
||||
int id,
|
||||
const char **name)
|
||||
{
|
||||
struct sftp_user_info *p;
|
||||
for (p = *cache ; p; p = p->next)
|
||||
if (p->id == id)
|
||||
{
|
||||
*name = p->name;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int
|
||||
sftp_cache_assoc(struct sftp_user_info **cache,
|
||||
int id,
|
||||
const char **name)
|
||||
{
|
||||
struct sftp_user_info **p;
|
||||
struct sftp_user_info *p;
|
||||
|
||||
for (pp = cache; (p = *pp); pp = &(p->next))
|
||||
if (p->id == id)
|
||||
{
|
||||
/* Reorder, putting the found element first. */
|
||||
*pp = p->next;
|
||||
p->next = *cache;
|
||||
*cache = p;
|
||||
|
||||
*name = p->name;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *
|
||||
sftp_cache_push(struct sftp_user_info **cache,
|
||||
int id, const char *name)
|
||||
{
|
||||
struct sftp_user_info *p = xmalloc(sizeof(struct sftp_user_info));
|
||||
p->id = id;
|
||||
p->name = name;
|
||||
p->next = *cache;
|
||||
*cache = p;
|
||||
|
||||
return name;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* idcache.h
|
||||
*
|
||||
*/
|
||||
|
||||
/* lsh, an implementation of the ssh protocol
|
||||
*
|
||||
* Copyright (C) 2001 Niels Möller
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef SFTP_IDCACHE_H_INCLUDED
|
||||
#define SFTP_IDCACHE_H_INCLUDED
|
||||
|
||||
struct sftp_user_info;
|
||||
|
||||
int
|
||||
sftp_cache_assoc(struct sftp_user_info **cache,
|
||||
int id,
|
||||
const char **name);
|
||||
|
||||
const char *
|
||||
sftp_cache_push(struct sftp_user_info **cache,
|
||||
int id, const char *name);
|
||||
|
||||
#endif /* SFTP_IDCACHE_H_INCLUDED */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,949 @@
|
|||
/* sftp-test-client.c
|
||||
*
|
||||
*/
|
||||
|
||||
/* lsh, an implementation of the ssh protocol
|
||||
*
|
||||
* Copyright (C) 2001 Niels Möller, Pontus Sköld
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "buffer.h"
|
||||
#include "sftp.h"
|
||||
#include "xmalloc.h"
|
||||
#include "client.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define SFTP_XFER_BLOCKSIZE 16384
|
||||
#define SFTP_VERSION 3
|
||||
|
||||
#define FATAL(x) do { fputs("sftp-test-client: " x "\n", stderr); exit(EXIT_FAILURE); } while (0)
|
||||
#define _FATAL(x) do { fputs("sftp-test-client: " x "\n", stderr); _exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
|
||||
|
||||
|
||||
static UINT32
|
||||
sftp_client_new_id(void)
|
||||
{
|
||||
/* Return a new (monotonically increasing) every time */
|
||||
static UINT32 curid=0;
|
||||
return curid++;
|
||||
}
|
||||
|
||||
static int
|
||||
sftp_client_get_id(struct sftp_input *i, UINT32 expected)
|
||||
{
|
||||
UINT32 id;
|
||||
return (sftp_get_uint32(i, &id)
|
||||
&& (id == expected));
|
||||
}
|
||||
|
||||
static void
|
||||
fork_server(char *name,
|
||||
struct client_ctx *ctx)
|
||||
{
|
||||
/* [0] for reading, [1] for writing */
|
||||
int stdin_pipe[2];
|
||||
int stdout_pipe[2];
|
||||
|
||||
if (pipe(stdin_pipe) < 0)
|
||||
FATAL("Creating stdin_pipe failed.");
|
||||
|
||||
if (pipe(stdout_pipe) < 0)
|
||||
FATAL("Creating stdout_pipe failed.");
|
||||
|
||||
switch(fork())
|
||||
{
|
||||
case -1:
|
||||
FATAL("fork failed.");
|
||||
default: /* Parent */
|
||||
{
|
||||
FILE *i;
|
||||
FILE *o;
|
||||
|
||||
close(stdin_pipe[0]);
|
||||
close(stdout_pipe[1]);
|
||||
|
||||
i = fdopen(stdout_pipe[0], "r");
|
||||
if (!i)
|
||||
FATAL("fdopen stdout_pipe failed.");
|
||||
|
||||
o = fdopen(stdin_pipe[1], "w");
|
||||
if (!o)
|
||||
FATAL("fdopen stdin_pipe failed.");
|
||||
|
||||
ctx->i = sftp_make_input(i);
|
||||
ctx->o = sftp_make_output(o);
|
||||
|
||||
return;
|
||||
}
|
||||
case 0: /* Child */
|
||||
if (dup2(stdin_pipe[0], STDIN_FILENO) < 0)
|
||||
_FATAL("dup2 for stdin failed.");
|
||||
if (dup2(stdout_pipe[1], STDOUT_FILENO) < 0)
|
||||
_FATAL("dup2 for stdout failed.");
|
||||
|
||||
close(stdin_pipe[0]);
|
||||
close(stdin_pipe[1]);
|
||||
close(stdout_pipe[0]);
|
||||
close(stdout_pipe[1]);
|
||||
|
||||
execl(name, name, NULL);
|
||||
|
||||
_FATAL("execl failed.");
|
||||
}
|
||||
}
|
||||
|
||||
/* The handshake packets are special, because they don't include any
|
||||
* request id. */
|
||||
static int
|
||||
client_handshake(struct client_ctx *ctx)
|
||||
{
|
||||
UINT8 msg;
|
||||
UINT32 version;
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_INIT);
|
||||
sftp_set_id(ctx->o, SFTP_VERSION);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
return (sftp_get_uint8(ctx->i, &msg)
|
||||
&& (msg == SSH_FXP_VERSION)
|
||||
&& sftp_get_uint32(ctx->i, &version)
|
||||
&& (version == SFTP_VERSION)
|
||||
&& sftp_get_eod(ctx->i));
|
||||
}
|
||||
|
||||
static int
|
||||
do_ls(struct client_ctx *ctx, const char *name)
|
||||
{
|
||||
UINT32 id;
|
||||
UINT32 status;
|
||||
UINT8* handle;
|
||||
UINT32 hlength;
|
||||
|
||||
UINT8 msg;
|
||||
int lsloop=1;
|
||||
int failure=0;
|
||||
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_OPENDIR); /* Send a OPENDIR message */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, strlen(name), name);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
/* None of these may fail */
|
||||
if ( !(sftp_get_uint8(ctx->i, &msg)
|
||||
&& (msg==SSH_FXP_HANDLE)
|
||||
&& sftp_client_get_id(ctx->i, id)
|
||||
&& (handle=sftp_get_string(ctx->i, &hlength)) ))
|
||||
return 0;
|
||||
|
||||
/* OK, we now have a successfull call and a handle to a directory. */
|
||||
|
||||
while ( lsloop )
|
||||
{
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_READDIR);
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, hlength, handle);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
if( !(sftp_get_uint8(ctx->i, &msg)
|
||||
&& sftp_client_get_id(ctx->i, id)))
|
||||
return 0;
|
||||
|
||||
if ( msg == SSH_FXP_NAME )
|
||||
{
|
||||
UINT32 count;
|
||||
struct sftp_attrib a;
|
||||
|
||||
sftp_get_uint32(ctx->i, &count );
|
||||
|
||||
while ( count-- )
|
||||
{
|
||||
UINT8* fname;
|
||||
UINT32 fnamel;
|
||||
|
||||
UINT8* lname;
|
||||
UINT32 lnamel;
|
||||
|
||||
sftp_input_clear_strings(ctx->i);
|
||||
|
||||
if (! ( (fname=sftp_get_string_auto(ctx->i, &fnamel))
|
||||
&& (lname=sftp_get_string_auto(ctx->i, &lnamel))
|
||||
&& sftp_get_attrib(ctx->i, &a)))
|
||||
return 0;
|
||||
|
||||
printf("%s\n", lname);
|
||||
}
|
||||
}
|
||||
else
|
||||
if ( msg == SSH_FXP_STATUS )
|
||||
{
|
||||
sftp_get_uint32(ctx->i, &status);
|
||||
lsloop=0; /* End of loop - EOF or failue */
|
||||
|
||||
if ( status != SSH_FX_EOF)
|
||||
failure=1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Time to close */
|
||||
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_CLOSE); /* Send a close message */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, hlength, handle);
|
||||
|
||||
sftp_free_string(handle);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
return (sftp_get_uint8(ctx->i, &msg)
|
||||
&& (msg==SSH_FXP_STATUS)
|
||||
&& sftp_client_get_id(ctx->i, id)
|
||||
&& sftp_get_uint32(ctx->i, &status)
|
||||
&& (status == SSH_FX_OK)
|
||||
&& !failure);
|
||||
}
|
||||
|
||||
static UINT8 *
|
||||
do_open(struct client_ctx *ctx,
|
||||
const char *name,
|
||||
UINT32 flags,
|
||||
const struct sftp_attrib *a,
|
||||
UINT32 *handle_length)
|
||||
{
|
||||
UINT8 msg;
|
||||
UINT32 id = sftp_client_new_id();
|
||||
|
||||
/* Send a OPEN message */
|
||||
sftp_set_msg(ctx->o, SSH_FXP_OPEN);
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, strlen(name), name );
|
||||
sftp_put_uint32(ctx->o, flags);
|
||||
sftp_put_attrib(ctx->o, a);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
/* None of these may fail */
|
||||
return (sftp_get_uint8(ctx->i, &msg)
|
||||
&& (msg==SSH_FXP_HANDLE)
|
||||
&& sftp_client_get_id(ctx->i, id))
|
||||
? sftp_get_string(ctx->i, handle_length)
|
||||
: NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
do_close(struct client_ctx *ctx,
|
||||
UINT32 handle_length,
|
||||
const UINT8 *handle)
|
||||
{
|
||||
UINT8 msg;
|
||||
UINT32 status;
|
||||
|
||||
UINT32 id = sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_CLOSE); /* Send a close message */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, handle_length, handle);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
/* None of these may fail */
|
||||
return (sftp_get_uint8(ctx->i, &msg)
|
||||
&& (msg==SSH_FXP_STATUS)
|
||||
&& sftp_client_get_id(ctx->i, id)
|
||||
&& sftp_get_uint32(ctx->i, &status)
|
||||
&& (status == SSH_FX_OK));
|
||||
}
|
||||
|
||||
static int
|
||||
do_get(struct client_ctx *ctx,
|
||||
const char *name,
|
||||
int dst)
|
||||
{
|
||||
UINT32 id;
|
||||
UINT8* handle;
|
||||
UINT32 handle_length;
|
||||
UINT32 status;
|
||||
|
||||
off_t curpos=0;
|
||||
|
||||
struct sftp_attrib a;
|
||||
|
||||
UINT8 msg;
|
||||
int getloop=1;
|
||||
int ok = 1;
|
||||
|
||||
sftp_clear_attrib(&a); /* Don't pass any information on how to open */
|
||||
|
||||
if (! (handle = do_open(ctx, name, SSH_FXF_READ, &a, &handle_length)))
|
||||
return 0;
|
||||
|
||||
/* OK, we now have a successfull call and file handle */
|
||||
|
||||
id=sftp_client_new_id();
|
||||
|
||||
while ( getloop )
|
||||
{
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_READ); /* Send a read request */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, handle_length, handle);
|
||||
sftp_put_uint64(ctx->o, curpos);
|
||||
sftp_put_uint32(ctx->o, SFTP_XFER_BLOCKSIZE);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
if( !(sftp_get_uint8(ctx->i, &msg)
|
||||
&& sftp_client_get_id(ctx->i, id)))
|
||||
return 0;
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case SSH_FXP_DATA:
|
||||
{
|
||||
UINT8 *data;
|
||||
UINT32 length;
|
||||
|
||||
data = sftp_get_string_auto(ctx->i, &length);
|
||||
curpos += length;
|
||||
|
||||
while (length)
|
||||
{
|
||||
int res;
|
||||
do
|
||||
res = write(dst, data, length);
|
||||
while ( (res < 0) && (errno = EINTR) );
|
||||
if (res < 0)
|
||||
{
|
||||
getloop=0;
|
||||
ok=0;
|
||||
break;
|
||||
}
|
||||
data +=res;
|
||||
length -= res;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SSH_FXP_STATUS:
|
||||
{
|
||||
sftp_get_uint32(ctx->i, &status);
|
||||
getloop=0; /* End of loop - EOF or failue */
|
||||
|
||||
if ( status != SSH_FX_EOF)
|
||||
ok=0;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Time to close */
|
||||
|
||||
if (!do_close(ctx, handle_length, handle))
|
||||
ok = 0;
|
||||
|
||||
sftp_free_string(handle);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
do_get(struct client_ctx *ctx,
|
||||
const char *lname,
|
||||
const char *rname,
|
||||
int cont,
|
||||
off_t contat)
|
||||
{
|
||||
UINT32 id;
|
||||
UINT32 status;
|
||||
UINT8* handle;
|
||||
UINT32 hlength;
|
||||
|
||||
off_t curpos=0;
|
||||
UINT32 rdatal;
|
||||
UINT8* rdata;
|
||||
|
||||
struct sftp_attrib a;
|
||||
|
||||
UINT8 msg;
|
||||
int getloop=1;
|
||||
int failure=0;
|
||||
int fd=-1;
|
||||
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_clear_attrib(&a); /* Don't pass any information on how to open */
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_OPEN); /* Send a OPEN message */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, strlen(rname), rname );
|
||||
sftp_put_uint32(ctx->o, SSH_FXF_READ ); /* Read mode only */
|
||||
sftp_put_attrib(ctx->o, &a);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
if ( !(sftp_get_uint8(ctx->i, &msg) && /* None of these may fail */
|
||||
msg==SSH_FXP_HANDLE &&
|
||||
sftp_client_get_id(ctx->i, id) &&
|
||||
(handle=sftp_get_string(ctx->i, &hlength))
|
||||
))
|
||||
return 0;
|
||||
|
||||
/* OK, we now have a successfull call and file handle */
|
||||
|
||||
id=sftp_client_new_id();
|
||||
sftp_set_msg(ctx->o, SSH_FXP_FSTAT); /* Send a FSTAT message */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, hlength, handle );
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
if ( !(sftp_get_uint8(ctx->i, &msg) && /* None of these may fail */
|
||||
msg==SSH_FXP_ATTRS &&
|
||||
sftp_client_get_id(ctx->i, id) &&
|
||||
sftp_get_attrib(ctx->i, &a)
|
||||
))
|
||||
{
|
||||
getloop=0; /* fstat failed - skip the loop */
|
||||
failure=1; /* failure (but we still need to close the file */
|
||||
}
|
||||
else
|
||||
{
|
||||
int openmode=0666; /* Default mode for open if server doesn't say
|
||||
otherwise */
|
||||
|
||||
if ( a.flags & SSH_FILEXFER_ATTR_PERMISSIONS )
|
||||
openmode=a.permissions & 0777;
|
||||
|
||||
if ( (fd=open( lname, O_CREAT | O_WRONLY, openmode )) < 0 )
|
||||
{
|
||||
getloop=0; /* Couldn't open local file - skip loop */
|
||||
failure=1;
|
||||
}
|
||||
|
||||
if ( !cont ) /* Continue an old transfer */
|
||||
curpos=0;
|
||||
else
|
||||
{
|
||||
if ( contat ) /* Position to continue at given? */
|
||||
curpos=contat;
|
||||
else
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if ( ! fstat(fd, &st ) ) /* Stat local file */
|
||||
{
|
||||
/* Failed (Fixme; is it plausible that the fstat fails but the
|
||||
rest works?) */
|
||||
failure=1;
|
||||
getloop=0;
|
||||
}
|
||||
else
|
||||
curpos=st.st_size; /* Continue at end of local file */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
while ( getloop )
|
||||
{
|
||||
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_READ); /* Send a read request */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, hlength, handle);
|
||||
sftp_put_uint64(ctx->o, curpos);
|
||||
sftp_put_uint32(ctx->o, SFTP_XFER_BLOCKSIZE);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
|
||||
if( !(sftp_get_uint8(ctx->i, &msg) &&
|
||||
sftp_client_get_id(ctx->i, id)
|
||||
))
|
||||
return 0;
|
||||
|
||||
if ( msg == SSH_FXP_DATA )
|
||||
{
|
||||
rdata=sftp_get_string_auto(ctx->i, &rdatal);
|
||||
/* Fixme; display this somehow */
|
||||
|
||||
if ( ( -1 == lseek(fd,curpos, SEEK_SET) ) ||
|
||||
( -1 == write(fd,rdata,rdatal) ) )
|
||||
{
|
||||
getloop=0;
|
||||
failure=1;
|
||||
}
|
||||
else
|
||||
curpos+=rdatal;
|
||||
|
||||
}
|
||||
else
|
||||
if ( msg == SSH_FXP_STATUS )
|
||||
{
|
||||
sftp_get_uint32(ctx->i, &status);
|
||||
getloop=0; /* End of loop - EOF or failue */
|
||||
|
||||
if ( status != SSH_FX_EOF)
|
||||
failure=1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Time to close */
|
||||
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_CLOSE); /* Send a close message */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, hlength, handle);
|
||||
|
||||
sftp_free_string(handle);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
if ( fd >= 0 && close(fd) )
|
||||
failure=1;
|
||||
|
||||
if ( !(
|
||||
sftp_get_uint8(ctx->i, &msg) && /* None of these may fail */
|
||||
msg==SSH_FXP_STATUS &&
|
||||
sftp_client_get_id(ctx->i, id) &&
|
||||
sftp_get_uint32(ctx->i, &status) &&
|
||||
status == SSH_FX_OK &&
|
||||
!failure
|
||||
))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
do_put(struct client_ctx *ctx,
|
||||
const char *name,
|
||||
int fd)
|
||||
{
|
||||
UINT32 id;
|
||||
UINT32 status;
|
||||
UINT8* handle;
|
||||
UINT32 handle_length;
|
||||
off_t curpos=0;
|
||||
|
||||
struct sftp_attrib a;
|
||||
|
||||
UINT8 msg;
|
||||
int putloop=1;
|
||||
int ok = 1;
|
||||
|
||||
sftp_clear_attrib(&a);
|
||||
|
||||
a.flags = 0;
|
||||
|
||||
if (! (handle = do_open(ctx, name, SSH_FXF_CREAT | SSH_FXF_WRITE, &a,
|
||||
&handle_length)))
|
||||
return 0;
|
||||
|
||||
/* OK, we now have a successfull call and file handle */
|
||||
|
||||
while ( putloop )
|
||||
{
|
||||
UINT8 buf[SFTP_XFER_BLOCKSIZE];
|
||||
int res;
|
||||
|
||||
do
|
||||
res = read(fd, buf, sizeof(buf));
|
||||
while ( (res < 0) && (errno == EINTR) );
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
putloop=0;
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !res )
|
||||
putloop=0;
|
||||
else
|
||||
{
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_WRITE); /* Send a read request */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, handle_length, handle);
|
||||
sftp_put_uint64(ctx->o, curpos);
|
||||
sftp_put_string(ctx->o, res, buf);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
curpos += res;
|
||||
|
||||
if (!sftp_read_packet(ctx->i))
|
||||
return 0;
|
||||
|
||||
if( !(sftp_get_uint8(ctx->i, &msg)
|
||||
&& sftp_client_get_id(ctx->i, id)))
|
||||
return 0;
|
||||
|
||||
if ( msg == SSH_FXP_STATUS )
|
||||
{
|
||||
sftp_get_uint32(ctx->i, &status);
|
||||
putloop=0; /* End of loop - EOF or failue */
|
||||
|
||||
if ( status != SSH_FX_OK )
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Time to close */
|
||||
|
||||
if (!do_close(ctx, handle_length, handle))
|
||||
ok = 0;
|
||||
|
||||
sftp_free_string(handle);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
do_put(struct client_ctx *ctx,
|
||||
const char *lname,
|
||||
const char *rname,
|
||||
int cont,
|
||||
off_t contat)
|
||||
{
|
||||
UINT32 id;
|
||||
UINT32 status;
|
||||
UINT8* handle;
|
||||
UINT32 hlength;
|
||||
off_t curpos=0;
|
||||
UINT8* wdata;
|
||||
ssize_t rbytes;
|
||||
|
||||
struct stat st;
|
||||
struct sftp_attrib a;
|
||||
|
||||
UINT8 msg;
|
||||
int putloop=1;
|
||||
int failure=0;
|
||||
int fd=-1;
|
||||
|
||||
sftp_clear_attrib(&a);
|
||||
|
||||
if ( ((fd=open( lname, O_RDONLY)) < 0) ||
|
||||
fstat(fd, &st) )
|
||||
return 0; /* Open or stat failed */
|
||||
|
||||
wdata=xmalloc(SFTP_XFER_BLOCKSIZE);
|
||||
|
||||
a.flags= ( SSH_FILEXFER_ATTR_PERMISSIONS |
|
||||
SSH_FILEXFER_ATTR_UIDGID ); /* Fixme; what should we pass? */
|
||||
|
||||
a.permissions=st.st_mode & 0777; /* Fixme; Macro for 0777? */
|
||||
a.uid=st.st_uid;
|
||||
a.gid=st.st_gid;
|
||||
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_OPEN); /* Send a OPEN message */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, strlen(rname), rname );
|
||||
sftp_put_uint32(ctx->o, SSH_FXF_CREAT | SSH_FXF_WRITE );
|
||||
sftp_put_attrib(ctx->o, &a);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
if ( !(
|
||||
sftp_get_uint8(ctx->i, &msg) && /* None of these may fail */
|
||||
msg==SSH_FXP_HANDLE &&
|
||||
sftp_client_get_id(ctx->i, id) &&
|
||||
(handle=sftp_get_string(ctx->i, &hlength))
|
||||
))
|
||||
return 0;
|
||||
|
||||
/* OK, we now have a successfull call and file handle */
|
||||
|
||||
id=sftp_client_new_id();
|
||||
sftp_set_msg(ctx->o, SSH_FXP_FSTAT); /* Send a FSTAT message */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, hlength, handle );
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
if ( !(
|
||||
sftp_get_uint8(ctx->i, &msg) && /* None of these may fail */
|
||||
msg==SSH_FXP_ATTRS &&
|
||||
sftp_client_get_id(ctx->i, id) &&
|
||||
sftp_get_attrib(ctx->i, &a)
|
||||
))
|
||||
{
|
||||
putloop=0; /* fstat failed - skip the loop */
|
||||
failure=1; /* failure (but we still need to close the file) */
|
||||
}
|
||||
|
||||
|
||||
if ( !cont ) /* Continue an old transfer? */
|
||||
curpos=0;
|
||||
else
|
||||
{
|
||||
if ( contat ) /* Position to continue at given? */
|
||||
curpos=contat;
|
||||
else
|
||||
{
|
||||
if ( a.flags & SSH_FILEXFER_ATTR_SIZE )
|
||||
curpos=a.size;
|
||||
/* Continue at end of remote file */
|
||||
}
|
||||
}
|
||||
|
||||
while ( putloop )
|
||||
{
|
||||
if (
|
||||
(-1 == ( lseek(fd, curpos ,SEEK_SET) ) ) ||
|
||||
(-1 == (rbytes=read(fd, wdata, SFTP_XFER_BLOCKSIZE )) )
|
||||
)
|
||||
{
|
||||
putloop=0;
|
||||
failure=1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !rbytes )
|
||||
putloop=0;
|
||||
else
|
||||
{
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_WRITE); /* Send a read request */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, hlength, handle);
|
||||
sftp_put_uint64(ctx->o, curpos);
|
||||
sftp_put_string(ctx->o, rbytes, wdata);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
curpos+=rbytes;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
|
||||
if( !(
|
||||
sftp_get_uint8(ctx->i, &msg) &&
|
||||
sftp_client_get_id(ctx->i, id)
|
||||
))
|
||||
return 0;
|
||||
|
||||
if ( msg == SSH_FXP_STATUS )
|
||||
{
|
||||
sftp_get_uint32(ctx->i, &status);
|
||||
putloop=0; /* End of loop - EOF or failue */
|
||||
|
||||
if ( status != SSH_FX_OK )
|
||||
failure=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Time to close */
|
||||
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_CLOSE); /* Send a close message */
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, hlength, handle);
|
||||
|
||||
sftp_free_string(handle);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
if ( fd >= 0 && close(fd) )
|
||||
failure=1;
|
||||
|
||||
free(wdata);
|
||||
|
||||
if ( !(
|
||||
sftp_get_uint8(ctx->i, &msg) && /* None of these may fail */
|
||||
msg==SSH_FXP_STATUS &&
|
||||
sftp_client_get_id(ctx->i, id) &&
|
||||
sftp_get_uint32(ctx->i, &status) &&
|
||||
status == SSH_FX_OK &&
|
||||
!failure
|
||||
))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
do_stat(struct client_ctx *ctx, const char *name)
|
||||
{
|
||||
UINT32 id;
|
||||
UINT8 msg;
|
||||
struct sftp_attrib a;
|
||||
|
||||
id=sftp_client_new_id();
|
||||
|
||||
sftp_set_msg(ctx->o, SSH_FXP_STAT);
|
||||
sftp_set_id(ctx->o, id);
|
||||
sftp_put_string(ctx->o, strlen(name), name);
|
||||
|
||||
if (!sftp_write_packet(ctx->o))
|
||||
return 0;
|
||||
|
||||
if (sftp_read_packet(ctx->i) <= 0)
|
||||
return 0;
|
||||
|
||||
if ( !(sftp_get_uint8(ctx->i, &msg) && /* None of these may fail */
|
||||
msg==SSH_FXP_ATTRS &&
|
||||
sftp_client_get_id(ctx->i, id) &&
|
||||
sftp_get_attrib(ctx->i, &a)
|
||||
))
|
||||
return 0;
|
||||
|
||||
/* Fixme; return this somehow */
|
||||
printf("Stat succeeded\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *werror_program_name = "sftp-test-client";
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct client_ctx ctx;
|
||||
int i;
|
||||
|
||||
if (argc < 2)
|
||||
FATAL("Too few args.");
|
||||
|
||||
fork_server(argv[1], &ctx);
|
||||
|
||||
if (!client_handshake(&ctx))
|
||||
FATAL("Handshake failed.");
|
||||
|
||||
for (i = 2; i < argc; i += 2)
|
||||
{
|
||||
int res;
|
||||
switch (argv[i][0])
|
||||
{
|
||||
case 'l': /* ls */
|
||||
/* Depends on argv[argc] == NULL */
|
||||
res = do_ls(&ctx, argv[i+1]);
|
||||
break;
|
||||
case 'g': /* get */
|
||||
res = do_get(&ctx, argv[i+1], STDOUT_FILENO);
|
||||
break;
|
||||
case 'p':
|
||||
res = do_put(&ctx, argv[i+1], STDIN_FILENO);
|
||||
break;
|
||||
case 's':
|
||||
res = do_stat(&ctx, argv[i+1]);
|
||||
break;
|
||||
default:
|
||||
FATAL("Bad arg");
|
||||
}
|
||||
if (!res)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/* sftp.h
|
||||
*/
|
||||
|
||||
#ifndef SFTP_SFTP_H_INCLUDED
|
||||
#define SFTP_SFTP_H_INCLUDED
|
||||
|
||||
/* Messages */
|
||||
enum sftp_msg_type {
|
||||
SSH_FXP_INIT = 1, /* 0x01 */
|
||||
SSH_FXP_VERSION = 2, /* 0x02 */
|
||||
SSH_FXP_OPEN = 3, /* 0x03 */
|
||||
SSH_FXP_CLOSE = 4, /* 0x04 */
|
||||
SSH_FXP_READ = 5, /* 0x05 */
|
||||
SSH_FXP_WRITE = 6, /* 0x06 */
|
||||
SSH_FXP_LSTAT = 7, /* 0x07 */
|
||||
SSH_FXP_FSTAT = 8, /* 0x08 */
|
||||
SSH_FXP_SETSTAT = 9, /* 0x09 */
|
||||
SSH_FXP_FSETSTAT = 10, /* 0x0a */
|
||||
SSH_FXP_OPENDIR = 11, /* 0x0b */
|
||||
SSH_FXP_READDIR = 12, /* 0x0c */
|
||||
SSH_FXP_REMOVE = 13, /* 0x0d */
|
||||
SSH_FXP_MKDIR = 14, /* 0x0e */
|
||||
SSH_FXP_RMDIR = 15, /* 0x0f */
|
||||
SSH_FXP_REALPATH = 16, /* 0x10 */
|
||||
SSH_FXP_STAT = 17, /* 0x11 */
|
||||
SSH_FXP_RENAME = 18, /* 0x12 */
|
||||
SSH_FXP_STATUS = 101, /* 0x65 */
|
||||
SSH_FXP_HANDLE = 102, /* 0x66 */
|
||||
SSH_FXP_DATA = 103, /* 0x67 */
|
||||
SSH_FXP_NAME = 104, /* 0x68 */
|
||||
SSH_FXP_ATTRS = 105, /* 0x69 */
|
||||
SSH_FXP_EXTENDED = 200, /* 0xc8 */
|
||||
SSH_FXP_EXTENDED_REPLY = 201, /* 0xc9 */
|
||||
};
|
||||
|
||||
/* Attribute flags */
|
||||
enum sftp_attr_flag {
|
||||
SSH_FILEXFER_ATTR_SIZE = 0x00000001,
|
||||
SSH_FILEXFER_ATTR_UIDGID = 0x00000002,
|
||||
SSH_FILEXFER_ATTR_PERMISSIONS = 0x00000004,
|
||||
SSH_FILEXFER_ATTR_ACMODTIME = 0x00000008,
|
||||
SSH_FILEXFER_ATTR_EXTENDED = 0x80000000,
|
||||
};
|
||||
|
||||
/* Open flags */
|
||||
enum sftp_open_flag {
|
||||
SSH_FXF_READ = 0x00000001,
|
||||
SSH_FXF_WRITE = 0x00000002,
|
||||
SSH_FXF_APPEND = 0x00000004,
|
||||
SSH_FXF_CREAT = 0x00000008,
|
||||
SSH_FXF_TRUNC = 0x00000010,
|
||||
SSH_FXF_EXCL = 0x00000020,
|
||||
};
|
||||
|
||||
/* Status codes */
|
||||
enum sftp_status {
|
||||
SSH_FX_OK = 0,
|
||||
SSH_FX_EOF = 1,
|
||||
SSH_FX_NO_SUCH_FILE = 2,
|
||||
SSH_FX_PERMISSION_DENIED = 3,
|
||||
SSH_FX_FAILURE = 4,
|
||||
SSH_FX_BAD_MESSAGE = 5,
|
||||
#if 0
|
||||
SSH_FX_NO_CONNECTION = 6,
|
||||
SSH_FX_CONNECTION_LOST = 7,
|
||||
#endif
|
||||
SSH_FX_OP_UNSUPPORTED = 8,
|
||||
};
|
||||
|
||||
#endif /* SFTP_SFTP_H_INCLUDED */
|
|
@ -0,0 +1 @@
|
|||
timestamp
|
|
@ -0,0 +1,9 @@
|
|||
TS_SH = connect-test get-1-test ls-1-test ls-2-test put-1-test
|
||||
|
||||
EXTRA_DIST = common.sh run-tests \
|
||||
setup-env teardown-env \
|
||||
$(TS_SH)
|
||||
|
||||
# I thought srcdir was exported automatically?
|
||||
check:
|
||||
srcdir="$(srcdir)" $(srcdir)/run-tests $(TS_SH)
|
|
@ -0,0 +1,175 @@
|
|||
# Makefile.in generated automatically by automake 1.4 from Makefile.am
|
||||
|
||||
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DESTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = ..
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
CC = @CC@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
PACKAGE = @PACKAGE@
|
||||
RANLIB = @RANLIB@
|
||||
VERSION = @VERSION@
|
||||
|
||||
TS_SH = connect-test get-1-test ls-1-test ls-2-test put-1-test
|
||||
|
||||
EXTRA_DIST = common.sh run-tests setup-env teardown-env $(TS_SH)
|
||||
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs
|
||||
CONFIG_HEADER = ../config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
DIST_COMMON = Makefile.am Makefile.in
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = tar
|
||||
GZIP_ENV = --best
|
||||
all: all-redirect
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps testsuite/Makefile
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
tags: TAGS
|
||||
TAGS:
|
||||
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
|
||||
subdir = testsuite
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
||||
fi; \
|
||||
done
|
||||
info-am:
|
||||
info: info-am
|
||||
dvi-am:
|
||||
dvi: dvi-am
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
installcheck-am:
|
||||
installcheck: installcheck-am
|
||||
install-exec-am:
|
||||
install-exec: install-exec-am
|
||||
|
||||
install-data-am:
|
||||
install-data: install-data-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
install: install-am
|
||||
uninstall-am:
|
||||
uninstall: uninstall-am
|
||||
all-am: Makefile
|
||||
all-redirect: all-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
|
||||
installdirs:
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
|
||||
maintainer-clean-generic:
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
clean: clean-am
|
||||
|
||||
distclean-am: distclean-generic clean-am
|
||||
|
||||
distclean: distclean-am
|
||||
|
||||
maintainer-clean-am: maintainer-clean-generic distclean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
|
||||
.PHONY: tags distdir info-am info dvi-am dvi check check-am \
|
||||
installcheck-am installcheck install-exec-am install-exec \
|
||||
install-data-am install-data install-am install uninstall-am uninstall \
|
||||
all-redirect all-am all installdirs mostlyclean-generic \
|
||||
distclean-generic clean-generic maintainer-clean-generic clean \
|
||||
mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
# I thought srcdir was exported automatically?
|
||||
check:
|
||||
srcdir="$(srcdir)" $(srcdir)/run-tests $(TS_SH)
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
|
@ -0,0 +1,21 @@
|
|||
# Common stuff for all test scripts.
|
||||
|
||||
set -e
|
||||
|
||||
TESTHOME=home
|
||||
export TESTHOME
|
||||
|
||||
# We need an absolute path.
|
||||
PROGRAMDIR=`cd .. && pwd`
|
||||
export PROGRAMDIR
|
||||
|
||||
if [ -n "$SFTP_DEBUG" ] ; then
|
||||
SERVER=debug-server
|
||||
else
|
||||
SERVER=sftp-server
|
||||
fi
|
||||
|
||||
client () {
|
||||
(cd $TESTHOME && "$PROGRAMDIR"/sftp-test-client "$PROGRAMDIR"/"$SERVER" "$@")
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#! /bin/sh
|
||||
|
||||
if [ -z "$srcdir" ] ; then
|
||||
srcdir=.
|
||||
fi
|
||||
|
||||
. $srcdir/common.sh
|
||||
|
||||
client
|
|
@ -0,0 +1,11 @@
|
|||
#! /bin/sh
|
||||
|
||||
if [ -z "$srcdir" ] ; then
|
||||
srcdir=.
|
||||
fi
|
||||
|
||||
. $srcdir/common.sh
|
||||
|
||||
client get "x1" | grep -q foo
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#! /bin/sh
|
||||
|
||||
if [ -z "$srcdir" ] ; then
|
||||
srcdir=.
|
||||
fi
|
||||
|
||||
. $srcdir/common.sh
|
||||
|
||||
# Match the d directory
|
||||
client ls "" | grep -q '^d.* d$'
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#! /bin/sh
|
||||
|
||||
if [ -z "$srcdir" ] ; then
|
||||
srcdir=.
|
||||
fi
|
||||
|
||||
. $srcdir/common.sh
|
||||
|
||||
# Match the d directory
|
||||
client ls "d" | grep -q ' x3$'
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#! /bin/sh
|
||||
|
||||
if [ -z "$srcdir" ] ; then
|
||||
srcdir=.
|
||||
fi
|
||||
|
||||
. $srcdir/common.sh
|
||||
|
||||
rm -f "$TESTHOME/d/new"
|
||||
echo data | client put "d/new" && \
|
||||
[ -r "$TESTHOME/d/new" ] && grep -q data "$TESTHOME/d/new"
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
#! /bin/bash
|
||||
|
||||
failed=0
|
||||
all=0
|
||||
|
||||
if [ -z "$srcdir" ] ; then
|
||||
srcdir=.
|
||||
fi
|
||||
|
||||
env_program () {
|
||||
if [ -x "$srcdir/$1" ] ; then
|
||||
if "$srcdir/$1"; then : ; else
|
||||
echo FAIL: $1
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
test_program () {
|
||||
if "$srcdir/$1" ; then
|
||||
echo PASS: ${1%-test}
|
||||
else
|
||||
echo FAIL: ${1%-test}
|
||||
failed=`expr $failed + 1`
|
||||
fi
|
||||
all=`expr $all + 1`
|
||||
}
|
||||
|
||||
env_program setup-env
|
||||
|
||||
if [ $# -eq 0 ] ; then
|
||||
for f in `cd $srcdir && echo *-test`; do test_program "$f"; done
|
||||
else
|
||||
for f in "$@" ; do test_program "$f"; done
|
||||
fi
|
||||
|
||||
if [ $failed -eq 0 ] ; then
|
||||
banner="All $all tests passed"
|
||||
else
|
||||
banner="$failed of $all tests failed"
|
||||
fi
|
||||
dashes=`echo "$banner" | sed s/./=/g`
|
||||
echo "$dashes"
|
||||
echo "$banner"
|
||||
echo "$dashes"
|
||||
|
||||
env_program teardown-env
|
||||
|
||||
[ "$failed" -eq 0 ]
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#! /bin/sh
|
||||
|
||||
if [ -z "$srcdir" ] ; then
|
||||
srcdir=.
|
||||
fi
|
||||
|
||||
. $srcdir/common.sh
|
||||
|
||||
# Clean up first.
|
||||
rm -rf $TESTHOME
|
||||
|
||||
# Create a directory to play with
|
||||
mkdir $TESTHOME
|
||||
cd $TESTHOME
|
||||
|
||||
# Create some files
|
||||
echo foo >x1
|
||||
echo bar >x2
|
||||
|
||||
mkdir d
|
||||
echo gazonk >d/x3
|
|
@ -0,0 +1,9 @@
|
|||
#! /bin/sh
|
||||
|
||||
if [ -z "$srcdir" ] ; then
|
||||
srcdir=.
|
||||
fi
|
||||
|
||||
. $srcdir/common.sh
|
||||
|
||||
rm -rf $TESTHOME
|
|
@ -0,0 +1,40 @@
|
|||
/* werror.c
|
||||
*
|
||||
* Simple diagnostics routines.
|
||||
*
|
||||
* $id$
|
||||
*/
|
||||
|
||||
#include "werror.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void
|
||||
werror(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
fprintf(stderr, "%s: ", werror_program_name);
|
||||
vfprintf(stderr, format, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
fatal(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
fprintf(stderr, "%s: ", werror_program_name);
|
||||
vfprintf(stderr, format, args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/* werror.h
|
||||
*
|
||||
* Simple diagnostics routines.
|
||||
*
|
||||
* $id$
|
||||
*/
|
||||
|
||||
#ifndef SFTP_WERROR_H_INCLUDED
|
||||
#define SFTP_WERROR_H_INCLUDED
|
||||
|
||||
/* For types and config stuff */
|
||||
#include "buffer.h"
|
||||
|
||||
extern const char *werror_program_name;
|
||||
|
||||
void werror(const char *format, ...) PRINTF_STYLE(1,2);
|
||||
void fatal(const char *format, ...) PRINTF_STYLE(1,2) NORETURN;
|
||||
|
||||
#endif /* SFTP_WERROR_H_INCLUDED */
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/* xmalloc.c
|
||||
*/
|
||||
|
||||
#include "xmalloc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void *
|
||||
xmalloc(size_t size)
|
||||
{
|
||||
void *p = malloc(size);
|
||||
if (!p)
|
||||
{
|
||||
fprintf(stderr, "Virtual memory exhausted\n");
|
||||
abort();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
char *
|
||||
xstrdup(const char *s)
|
||||
{
|
||||
size_t length = strlen(s);
|
||||
char *p = xmalloc(length + 1);
|
||||
memcpy(p, s, length);
|
||||
p[length] = '\0';
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void *
|
||||
xrealloc(void *old, size_t size)
|
||||
{
|
||||
void *p = realloc(old, size);
|
||||
if (!p)
|
||||
{
|
||||
fprintf(stderr, "Virtual memory exhausted\n");
|
||||
abort();
|
||||
}
|
||||
return p;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/* xmalloc.h
|
||||
*/
|
||||
|
||||
#ifndef SFTP_XMALLOC_H_INCLUDED
|
||||
#define SFTP_XMALLOC_H_INCLUDED
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void *
|
||||
xmalloc(size_t size);
|
||||
|
||||
char *
|
||||
xstrdup(const char *s);
|
||||
|
||||
void *
|
||||
xrealloc(void *old, size_t size);
|
||||
|
||||
#endif /* SFTP_XMALLOC_H_INCLUDED */
|
Loading…
Reference in New Issue