first import

This commit is contained in:
chombier 2001-09-18 16:39:21 +00:00
parent 9b784c8588
commit 5b5e0e778c
35 changed files with 9996 additions and 0 deletions

13
lsh/src/sftp/Makefile.am Normal file
View File

@ -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

479
lsh/src/sftp/Makefile.in Normal file
View File

@ -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:

2
lsh/src/sftp/acconfig.h Normal file
View File

@ -0,0 +1,2 @@
/* Define if the compiler understands __attribute__ */
#undef HAVE_GCC_ATTRIBUTE

215
lsh/src/sftp/aclocal.m4 vendored Normal file
View File

@ -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
])

605
lsh/src/sftp/buffer.c Normal file
View File

@ -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);
}
}

201
lsh/src/sftp/buffer.h Normal file
View File

@ -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 */

154
lsh/src/sftp/client.c Normal file
View File

@ -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);
}

60
lsh/src/sftp/client.h Normal file
View File

@ -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 */

67
lsh/src/sftp/config.h.in Normal file
View File

@ -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

4778
lsh/src/sftp/configure vendored Normal file

File diff suppressed because it is too large Load Diff

74
lsh/src/sftp/configure.in Normal file
View File

@ -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])

212
lsh/src/sftp/dump-hex.c Normal file
View File

@ -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;
}
}

260
lsh/src/sftp/filemode.c Normal file
View File

@ -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);
}

14
lsh/src/sftp/filemode.h Normal file
View File

@ -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));

88
lsh/src/sftp/idcache.c Normal file
View File

@ -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;
}

37
lsh/src/sftp/idcache.h Normal file
View File

@ -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 */

1257
lsh/src/sftp/sftp-server.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

70
lsh/src/sftp/sftp.h Normal file
View File

@ -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 */

1
lsh/src/sftp/stamp-h.in Normal file
View File

@ -0,0 +1 @@
timestamp

View File

@ -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)

View File

@ -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:

View File

@ -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" "$@")
}

View File

@ -0,0 +1,9 @@
#! /bin/sh
if [ -z "$srcdir" ] ; then
srcdir=.
fi
. $srcdir/common.sh
client

View File

@ -0,0 +1,11 @@
#! /bin/sh
if [ -z "$srcdir" ] ; then
srcdir=.
fi
. $srcdir/common.sh
client get "x1" | grep -q foo

View File

@ -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$'

View File

@ -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$'

View File

@ -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"

View File

@ -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 ]

View File

@ -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

View File

@ -0,0 +1,9 @@
#! /bin/sh
if [ -z "$srcdir" ] ; then
srcdir=.
fi
. $srcdir/common.sh
rm -rf $TESTHOME

40
lsh/src/sftp/werror.c Normal file
View File

@ -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);
}

20
lsh/src/sftp/werror.h Normal file
View File

@ -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 */

41
lsh/src/sftp/xmalloc.c Normal file
View File

@ -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;
}

18
lsh/src/sftp/xmalloc.h Normal file
View File

@ -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 */