uncommitted - gesftpserver

Ready changes

Summary

Import uploads missing from VCS:

Diff

diff --git a/.pc/.quilt_patches b/.pc/.quilt_patches
new file mode 100644
index 0000000..6857a8d
--- /dev/null
+++ b/.pc/.quilt_patches
@@ -0,0 +1 @@
+debian/patches
diff --git a/.pc/.quilt_series b/.pc/.quilt_series
new file mode 100644
index 0000000..c206706
--- /dev/null
+++ b/.pc/.quilt_series
@@ -0,0 +1 @@
+series
diff --git a/.pc/.version b/.pc/.version
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/.pc/.version
@@ -0,0 +1 @@
+2
diff --git a/.pc/applied-patches b/.pc/applied-patches
new file mode 100644
index 0000000..e69de29
diff --git a/CHANGES.md b/CHANGES.md
index 54c1c82..5e29aeb 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,12 @@
 # Release History
 
+## Changes in version 2
+
+* Fix interpretation of malformed handles
+* Correct attribute ordering. Bug fix from Bernd Holzmüller.
+* Tests use Python 3
+* Build fixes
+
 ## Changes in version 1
 
 * Fix attribute formatting in v3 directory listings.
diff --git a/Makefile.am b/Makefile.am
index 9645424..e59b867 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
 # This file is part of the Green End SFTP Server.
-# Copyright (C) 2007, 2011, 2014 Richard Kettlewell
+# Copyright (C) 2007, 2011,14,16,18 Richard Kettlewell
 #
 # 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
@@ -52,15 +52,15 @@ all: ${SEDOUTPUTS}
 check: gesftpserver sftpclient pwtest aliases
 	rm -f *.gcda *.gcov
 	./pwtest
-	srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory tests $(TESTS)
-	srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory rotests --server ./gesftpserver-ro $(ROTESTS)
-	${GCOV} ${srcdir}/*.c  | ${PYTHON24} ${srcdir}/format-gconv-report --html .
+	srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --directory tests $(TESTS)
+	srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --directory rotests --server ./gesftpserver-ro $(ROTESTS)
+	${GCOV} ${srcdir}/*.c  | ${PYTHON3} ${srcdir}/format-gconv-report --html .
 
 #${srcdir}/paramiko-test
 
 check-valgrind: gesftpserver-valgrind sftpclient pwtest aliases
 	rm -f ,valgrind*
-	srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory tests --server ./gesftpserver-valgrind $(TESTS)
+	srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --debug --directory tests --server ./gesftpserver-valgrind $(TESTS)
 
 aliases: gesftpserver-ro gesftpserver-debug gesftpserver-ro-debug \
 		gesftpserver-valgrind
diff --git a/README.md b/README.md
index ae3ba2b..da8c6a2 100644
--- a/README.md
+++ b/README.md
@@ -9,14 +9,15 @@ possible to use it as a drop-in replacement for the OpenSSH server.
 Requirements
 ------------
 
-This software runs under Linux, Mac OS X and FreeBSD.  It may work
-on other UNIX platforms.
+This software runs under Linux and macOS.
+It may work on other UNIX platforms.
 
 Installation
 ------------
 
 The general procedure is:
 
+    ./autogen.sh
     ./configure
     make check       # builds software and runs tests
     make install     # probably as root
@@ -36,7 +37,9 @@ don’t care.
 You will need iconv and readline libraries.
 
 It’s best to run `make check` before installing.  This requires
-[Python](http://www.python.org/) to be installed.
+[Python 3](http://www.python.org/) to be installed:
+
+    apt install python3 python3-termcolors
 
 Status
 ------
@@ -84,7 +87,7 @@ If you send patches, please use `diff -u` format.
 Licence
 -------
 
-Copyright (C) 2007, 2009-2011, 2014, 2016 Richard Kettlewell
+Copyright (C) 2007, 2009-2011, 2014-18 Richard Kettlewell
 
 Portions copyright (C) 2015 Michel Kraus
 
diff --git a/acinclude.m4 b/acinclude.m4
index a3b2111..3862f9c 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1,5 +1,5 @@
 # This file is part of the Green End SFTP Server.
-# Copyright (C) 2007, 2011 Richard Kettlewell
+# Copyright (C) 2007, 2011,14,15,18 Richard Kettlewell
 #
 # 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
@@ -45,7 +45,7 @@ AC_DEFUN([RJK_BUILDSYS_MISC],[
     # extra includes
     if test "$host" = "$build"; then
       case $host_os in
-      freebsd* ) 
+      freebsd* )
         rjk_cv_extraincludes=/usr/local/include
         ;;
       esac
@@ -62,7 +62,7 @@ AC_DEFUN([RJK_BUILDSYS_MISC],[
     rjk_cv_extralibs=none
     if test "$host" = "$build"; then
       case $host_os in
-      freebsd* ) 
+      freebsd* )
         rjk_cv_extralibs=/usr/local/lib
         ;;
       esac
@@ -250,28 +250,26 @@ AC_DEFUN([RJK_GETOPT],[
   ])
 ])
 
-AC_DEFUN([RJK_PYTHON24],[
-  AC_CACHE_CHECK([for Python 2.4 or better],[rjk_cv_python24],[
-    if python24 -V >/dev/null 2>&1; then
-      rjk_cv_python24=python24
-    elif python2.4 -V >/dev/null 2>&1; then
-      rjk_cv_python24=python2.4
+AC_DEFUN([RJK_PYTHON3],[
+  AC_CACHE_CHECK([for Python 3],[rjk_cv_python3],[
+    if python3 -V >/dev/null 2>&1; then
+      rjk_cv_python3=python3
     elif python -V >confpyver 2>&1; then
       read p v < confpyver
       case "$v" in
-      1* | 2.0* | 2.1* | 2.2* | 2.3* )
+      1* | 2* )
         ;;
       * )
-        rjk_cv_python24=python
+        rjk_cv_python3=python
         ;;
       esac
     fi
     rm -f confpyver
-    if test "$rjk_cv_python24" = ""; then
-      AC_MSG_ERROR([cannot find Python 2.4 or better])
+    if test "$rjk_cv_python3" = ""; then
+      AC_MSG_ERROR([cannot find Python 3.x])
     fi
   ])
-  AC_SUBST([PYTHON24],[$rjk_cv_python24])
+  AC_SUBST([PYTHON3],[$rjk_cv_python3])
 ])
 
 dnl Local Variables:
diff --git a/alloc.c b/alloc.c
index ceb318e..326efca 100644
--- a/alloc.c
+++ b/alloc.c
@@ -83,7 +83,7 @@ struct allocator *sftp_alloc_init(struct allocator *a) {
  * @return Number of blocks necessary to contain @p nbytes
  */
 static inline size_t blocks(size_t nbytes) {
-  return nbytes / sizeof (union block) + !!(nbytes % sizeof (union block));
+  return nbytes / sizeof(union block) + !!(nbytes % sizeof(union block));
 }
 
 void *sftp_alloc(struct allocator *a, size_t n) {
@@ -94,15 +94,15 @@ void *sftp_alloc(struct allocator *a, size_t n) {
   if(!m)
     return 0;
   assert(a != 0);
-  assert(m != SIZE_MAX);                /* ...and so m+1 > 0 */
+  assert(m != SIZE_MAX); /* ...and so m+1 > 0 */
   /* See if there's enough room */
   if(!(c = a->chunks) || c->left < m) {
     /* Make sure we allocate enough space */
     const size_t cs = m >= NBLOCKS ? m + 1 : NBLOCKS;
-    /* xcalloc -> calloc which 0-fills */
+    /* sftp_xcalloc -> calloc which 0-fills */
     union block *nb;
 
-    nb = xcalloc(cs, sizeof (union block));
+    nb = sftp_xcalloc(cs, sizeof(union block));
     c = &nb->c;
     c->next = a->chunks;
     c->ptr = nb + 1;
@@ -112,20 +112,21 @@ void *sftp_alloc(struct allocator *a, size_t n) {
   assert(m <= c->left);
   /* We always return 0-filled memory.  In this case we fill by block, which is
    * guaranteed to be at least enough (compare below). */
-  memset(c->ptr, 0, m * sizeof (union block));
+  sftp_memset(c->ptr, 0, m * sizeof(union block));
   c->left -= m;
   c->ptr += m;
   return c->ptr - m;
 }
 
-void *sftp_alloc_more(struct allocator *a, void *ptr, size_t oldn, size_t newn) {
+void *sftp_alloc_more(struct allocator *a, void *ptr, size_t oldn,
+                      size_t newn) {
   const size_t oldm = blocks(oldn), newm = blocks(newn);
   void *newptr;
 
   if(ptr) {
     assert(a->chunks != 0);
-    D(("ptr=%p oldm=%zu a->chunks->ptr=%p blocksize=%zu",
-       ptr, oldm, a->chunks->ptr, sizeof(union block)));
+    D(("ptr=%p oldm=%zu a->chunks->ptr=%p blocksize=%zu", ptr, oldm,
+       a->chunks->ptr, sizeof(union block)));
     if((union block *)ptr + oldm == a->chunks->ptr) {
       /* ptr is the most recently allocated block.  We could do better and
        * search all the chunks for it. */
@@ -141,7 +142,7 @@ void *sftp_alloc_more(struct allocator *a, void *ptr, size_t oldn, size_t newn)
         /* 0-fill the new space.  Note that we do this in byte terms (compare
          * above), to deal with the case where the allocation shrinks by (say)
          * a single non-zero byte but then expands again. */
-        memset((char *)ptr + oldn, 0, newn - oldn);
+        sftp_memset((char *)ptr + oldn, 0, newn - oldn);
         return ptr;
       }
       /* If we get here then we are expanding but there is not enough space to
@@ -153,7 +154,7 @@ void *sftp_alloc_more(struct allocator *a, void *ptr, size_t oldn, size_t newn)
     }
     /* We have no choice but to allocate new space */
     newptr = sftp_alloc(a, newn);
-    memcpy(newptr, ptr, oldn);
+    sftp_memcpy(newptr, ptr, oldn);
     return newptr;
   } else
     /* There was no old allocation, just create a new one the easy way */
diff --git a/alloc.h b/alloc.h
index 37a0ee2..c267b0f 100644
--- a/alloc.h
+++ b/alloc.h
@@ -21,7 +21,7 @@
 /** @file alloc.h @brief Allocator interface */
 
 #ifndef ALLOC_H
-#define ALLOC_H
+#  define ALLOC_H
 
 struct chunk;
 
diff --git a/charset.c b/charset.c
index bdb8013..8611178 100644
--- a/charset.c
+++ b/charset.c
@@ -32,13 +32,13 @@ wchar_t *sftp_mbs2wcs(const char *s) {
   wchar_t *ws;
   size_t len;
   mbstate_t ps;
-  
-  memset(&ps, 0, sizeof ps);
+
+  sftp_memset(&ps, 0, sizeof ps);
   len = mbsrtowcs(0, &s, 0, &ps);
   if(len == (size_t)-1)
     return 0;
-  ws = xcalloc(len + 1, sizeof *ws);
-  memset(&ps, 0, sizeof ps);
+  ws = sftp_xcalloc(len + 1, sizeof *ws);
+  sftp_memset(&ps, 0, sizeof ps);
   mbsrtowcs(ws, &s, len, &ps);
   return ws;
 }
@@ -51,7 +51,7 @@ int sftp_iconv(struct allocator *a, iconv_t cd, char **sp) {
   const char *inbuf;
   char *outbuf, *output;
   size_t inbytesleft, outbytesleft;
-  
+
   assert(cd != 0);
   do {
     output = sftp_alloc(a, outputsize);
diff --git a/charset.h b/charset.h
index dc03192..c73325f 100644
--- a/charset.h
+++ b/charset.h
@@ -21,10 +21,10 @@
 /** @file charset.h @brief Character conversion interface */
 
 #ifndef CHARSET_H
-#define CHARSET_H
+#  define CHARSET_H
 
-#include <wchar.h>
-#include <iconv.h>
+#  include <wchar.h>
+#  include <iconv.h>
 
 /** @brief Convert a multibyte string to a wide string
  * @param s Multibyte string to convert
diff --git a/configure.ac b/configure.ac
index 29ffee1..4de626c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
 # This file is part of the Green End SFTP Server.
-# Copyright (C) 2007, 2011, 2014, 2015 Richard Kettlewell
+# Copyright (C) 2007, 2011, 2014-2016, 2018 Richard Kettlewell
 #
 # 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
@@ -17,7 +17,7 @@
 # USA
 
 # Process this file with autoconf to produce a configure script.
-AC_INIT(sftpserver, 1, rjk@greenend.org.uk)
+AC_INIT(sftpserver, 2, rjk@greenend.org.uk)
 AC_CONFIG_AUX_DIR([config.aux])
 AM_INIT_AUTOMAKE([foreign])
 AC_CONFIG_SRCDIR([alloc.c])
@@ -55,7 +55,7 @@ RJK_GCC_WARNINGS
 RJK_GCC_ATTRS
 RJK_STAT_TIMESPEC
 RJK_GETOPT
-RJK_PYTHON24
+RJK_PYTHON3
 
 dnl See commentary in v3.c for what's going on here
 AC_MSG_CHECKING([whether to reverse SSH_FXP_SYMLINK arguments])
diff --git a/daemon.c b/daemon.c
index 4a26229..5e0bb7c 100644
--- a/daemon.c
+++ b/daemon.c
@@ -1,3 +1,4 @@
+// clang-format off
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
diff --git a/debian/changelog b/debian/changelog
index a69769f..b7cec20 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,25 @@
+gesftpserver (2~ds-1) unstable; urgency=medium
+
+  [ upstream ]
+  * new release
+
+  [ Jonas Smedegaard ]
+  * update git-buildpackage config:
+    + use DEP-14 git branches
+    + enable automatic DEP-14 branch name handling
+    + add usage config
+  * update watch file:
+    + set dversionmangle=auto
+    + set pgpmode=auto
+  * add upstream PGP signing-key
+  * update copyright info: update coverage
+  * declare compliance with Debian Policy 4.6.1
+  * use debhelper compatibility level 13;
+    tighten build-dependency on debhelper-compat
+  * drop patch 1001 to use python3, fixed upstream
+
+ -- Jonas Smedegaard <dr@jones.dk>  Fri, 12 Aug 2022 08:00:23 +0200
+
 gesftpserver (1~ds-3) unstable; urgency=medium
 
   [ lintian brush ]
diff --git a/debian/control b/debian/control
index fa7b596..f91aee4 100644
--- a/debian/control
+++ b/debian/control
@@ -3,10 +3,10 @@ Section: utils
 Priority: optional
 Maintainer: Jonas Smedegaard <dr@jones.dk>
 Build-Depends:
- debhelper-compat (= 12),
+ debhelper-compat (= 13),
  libreadline-dev,
  python3
-Standards-Version: 4.5.0
+Standards-Version: 4.6.1
 Vcs-Git: https://salsa.debian.org/debian/gesftpserver.git
 Vcs-Browser: https://salsa.debian.org/debian/gesftpserver
 Homepage: https://www.greenend.org.uk/rjk/sftpserver/
diff --git a/debian/copyright b/debian/copyright
index c68747e..c1047a4 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -19,7 +19,8 @@ Files-Excluded:
  tests/truncate6~
 
 Files: *
-Copyright: 2007,2009-2011,2014-2016, Richard Kettlewell
+Copyright:
+  2007,2009-2011,2014-2016, 2018  Richard Kettlewell
 License-Grant:
  This program is free software;
  you can redistribute it and/or modify it
@@ -29,7 +30,8 @@ License-Grant:
 License: GPL-2+
 
 Files: getopt*
-Copyright: 1987-2000, Free Software Foundation, Inc.
+Copyright:
+  1987-2000  Free Software Foundation, Inc.
 License-Grant:
  The GNU C Library is free software;
  you can redistribute it and/or modify it
@@ -39,11 +41,13 @@ License-Grant:
 License: LGPL-2+
 
 Files: daemon.c
-Copyright: 1990, 1993
+Copyright:
+  1990, 1993  The Regents of the University of California
 License: BSD-3-Clause~Regents~4
 
 Files: debian/*
-Copyright: 2012-2019, Jonas Smedegaard <dr@jones.dk>
+Copyright:
+  2012-2020, 2022  Jonas Smedegaard <dr@jones.dk>
 License-Grant:
  This program is free software;
  you can redistribute it and/or modify it
@@ -53,7 +57,8 @@ License-Grant:
 License: GPL-3+
 
 Files: debian/patches/0*
-Copyright: Richard Kettlewell
+Copyright:
+  Richard Kettlewell
 License: GPL-2+
 Comment:
  Patches cherry-picked upstream is assumed to be covered
diff --git a/debian/copyright_hints b/debian/copyright_hints
index cc9d42e..b3000f8 100644
--- a/debian/copyright_hints
+++ b/debian/copyright_hints
@@ -5,13 +5,16 @@ Source: FIXME
 Disclaimer: Autogenerated by CDBS
 
 Files: CHANGES.md
- debian/compat
+ debian/NEWS
  debian/control
  debian/gbp.conf
  debian/patches/README
  debian/patches/series
  debian/rules
  debian/source/format
+ debian/source/lintian-overrides
+ debian/upstream
+ debian/upstream/signing-key.asc
  debian/watch
  rotests/rotest3456
  rotests/rotest56
@@ -84,9 +87,7 @@ Copyright: NONE
 License: UNKNOWN
  FIXME
 
-Files: Makefile.am
- acinclude.m4
- alloc.c
+Files: alloc.c
  alloc.h
  charset.c
  charset.h
@@ -141,38 +142,43 @@ Copyright: 2007, 2009, 2011, 2014, Richard Kettlewell
   2007, 2010-2011, 2014, 2016, Richard Kettlewell
   2007, 2010-2011, Richard Kettlewell
   2007, 2011, 2014, Richard Kettlewell
-  2007, 2011, 2014-2015, Richard Kettlewell
+  2007, 2011, 2014-2016, 2018, Richard Kettlewell
+  2007, 2011, 2016, 2018, Richard Kettlewell
   2007, 2011, 2016, Richard Kettlewell
   2007, 2011, Richard Kettlewell
   2007, 2016, Richard Kettlewell
+  2007, 2018, Richard Kettlewell
   2007, Richard Kettlewell
   2014, Richard Kettlewell
 License: GPL-2+
  FIXME
 
 Files: daemon.c
-Copyright: 1990, 1993, The Regents of the University of California.
+Copyright: 1990, 1993
 License: BSD-3-clause
  FIXME
 
 Files: COPYING
 Copyright: 1989, 1991, Free Software Foundation, Inc.,
-  <year> <name of author>
-  disclaimer" for the program, if
-  ed by the Free
-  ed interfaces, the
-  interest in the program
-  the software, and
-  year name of author
-License: GPL-2+
+License: GPL-2
  FIXME
 
 Files: README.md
-Copyright: 2007, 2009-2011, 2014, 2016, Richard Kettlewell
+Copyright: 2007, 2009-2011, 2014, -18 Richard Kettlewell
   2015, Michel Kraus
 License: GPL-2+
  FIXME
 
+Files: acinclude.m4
+Copyright: 2007, 2011, 14,15,18 Richard Kettlewell
+License: GPL-2+
+ FIXME
+
+Files: Makefile.am
+Copyright: 2007, 2011, 14,16,18 Richard Kettlewell
+License: GPL-2+
+ FIXME
+
 Files: debian/copyright-check
 Copyright: 2016-2019, Jonas Smedegaard <dr@jones.dk>
 License: GPL-3+
@@ -199,13 +205,3 @@ Copyright: 2007, 2011, 2016, Richard Kettlewell
 License: UNKNOWN
  FIXME
 
-Files: debian/source/lintian-overrides
-Copyright: GPL-2+
-  GPL-3+
-  LGPL-2+
-  gpl-2+
-  gpl-3+
-  lgpl-2+
-License: UNKNOWN
- FIXME
-
diff --git a/debian/gbp.conf b/debian/gbp.conf
index 2a594ca..c6859d1 100644
--- a/debian/gbp.conf
+++ b/debian/gbp.conf
@@ -1,6 +1,15 @@
-# Configuration file for git-buildpackage and friends
+# clone this source:       gbp clone $PKG_GIT_URL
+# track upstream source:   git remote add upstream-git $UPSTREAM_GIT_URL
+# update this source:      gbp pull
+# update upstream source:  git fetch upstream-git --tags
+# import upstream release: gbp import-orig --upstream-vcs-tag=$VERSION --uscan
+# build package:           gbp buildpackage
+# publish source release:  gbp tag && gbp push
 
 [DEFAULT]
 pristine-tar = True
 sign-tags = True
 filter = */.git*
+debian-branch = debian/latest
+upstream-branch = upstream/latest
+dist = DEP14
diff --git a/debian/patches/1001_python3.patch b/debian/patches/1001_python3.patch
deleted file mode 100644
index d76fc08..0000000
--- a/debian/patches/1001_python3.patch
+++ /dev/null
@@ -1,162 +0,0 @@
-Description: Use Python 3
-Author: Jonas Smedegaard <dr@jones.dk>
-Last-Update: 2019-08-30
----
-This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -52,15 +52,15 @@
- check: gesftpserver sftpclient pwtest aliases
- 	rm -f *.gcda *.gcov
- 	./pwtest
--	srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory tests $(TESTS)
--	srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory rotests --server ./gesftpserver-ro $(ROTESTS)
--	${GCOV} ${srcdir}/*.c  | ${PYTHON24} ${srcdir}/format-gconv-report --html .
-+	srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --directory tests $(TESTS)
-+	srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --directory rotests --server ./gesftpserver-ro $(ROTESTS)
-+	${GCOV} ${srcdir}/*.c  | ${PYTHON3} ${srcdir}/format-gconv-report --html .
- 
- #${srcdir}/paramiko-test
- 
- check-valgrind: gesftpserver-valgrind sftpclient pwtest aliases
- 	rm -f ,valgrind*
--	srcdir=${srcdir} ${PYTHON24} ${srcdir}/run-tests --directory tests --server ./gesftpserver-valgrind $(TESTS)
-+	srcdir=${srcdir} ${PYTHON3} ${srcdir}/run-tests --directory tests --server ./gesftpserver-valgrind $(TESTS)
- 
- aliases: gesftpserver-ro gesftpserver-debug gesftpserver-ro-debug \
- 		gesftpserver-valgrind
---- a/acinclude.m4
-+++ b/acinclude.m4
-@@ -250,28 +250,26 @@
-   ])
- ])
- 
--AC_DEFUN([RJK_PYTHON24],[
--  AC_CACHE_CHECK([for Python 2.4 or better],[rjk_cv_python24],[
--    if python24 -V >/dev/null 2>&1; then
--      rjk_cv_python24=python24
--    elif python2.4 -V >/dev/null 2>&1; then
--      rjk_cv_python24=python2.4
-+AC_DEFUN([RJK_PYTHON3],[
-+  AC_CACHE_CHECK([for Python 3 or better],[rjk_cv_python3],[
-+    if python3 -V >/dev/null 2>&1; then
-+      rjk_cv_python3=python3
-     elif python -V >confpyver 2>&1; then
-       read p v < confpyver
-       case "$v" in
--      1* | 2.0* | 2.1* | 2.2* | 2.3* )
-+      1* | 2* )
-         ;;
-       * )
--        rjk_cv_python24=python
-+        rjk_cv_python3=python
-         ;;
-       esac
-     fi
-     rm -f confpyver
--    if test "$rjk_cv_python24" = ""; then
--      AC_MSG_ERROR([cannot find Python 2.4 or better])
-+    if test "$rjk_cv_python3" = ""; then
-+      AC_MSG_ERROR([cannot find Python 3 or better])
-     fi
-   ])
--  AC_SUBST([PYTHON24],[$rjk_cv_python24])
-+  AC_SUBST([PYTHON3],[$rjk_cv_python3])
- ])
- 
- dnl Local Variables:
---- a/configure.ac
-+++ b/configure.ac
-@@ -55,7 +55,7 @@
- RJK_GCC_ATTRS
- RJK_STAT_TIMESPEC
- RJK_GETOPT
--RJK_PYTHON24
-+RJK_PYTHON3
- 
- dnl See commentary in v3.c for what's going on here
- AC_MSG_CHECKING([whether to reverse SSH_FXP_SYMLINK arguments])
---- a/format-gconv-report
-+++ b/format-gconv-report
-@@ -1,4 +1,4 @@
--#! /usr/bin/env python
-+#! /usr/bin/env python3
- # This file is part of the Green End SFTP Server.
- # Copyright (C) 2007 Richard Kettlewell
- #
-@@ -29,7 +29,7 @@
-     return c
- 
- def sgmlquote(s):
--  return string.join(map(sgmlquotechar, s),'')
-+  return string.join(list(map(sgmlquotechar, s)),'')
- 
- percent = {}
- total_lines = 0
-@@ -64,13 +64,13 @@
-   elif percent[a] > percent[b]: return 1
-   else: return 0
- 
--keys = percent.keys()
-+keys = list(percent.keys())
- keys.sort(cmp)
- 
- if len(keys):
-   for k in keys:
--    print "%20s: %d%%" % (k, percent[k])
--  print "Total coverage: %d%%" % (100 * (covered_lines / total_lines))
-+    print("%20s: %d%%" % (k, percent[k]))
-+  print("Total coverage: %d%%" % (100 * (covered_lines / total_lines)))
- 
- if htmldir is not None and len(keys):
-   index = open(os.path.join(htmldir, "index.html"), "w")
---- a/run-tests
-+++ b/run-tests
-@@ -1,4 +1,4 @@
--#! /usr/bin/env python
-+#! /usr/bin/env python3
- #
- # This file is part of the Green End SFTP Server.
- # Copyright (C) 2007, 2011, 2016 Richard Kettlewell
-@@ -29,7 +29,7 @@
- def rmrf(path):
-     if os.path.lexists(path):
-         if (not os.path.islink(path)) and os.path.isdir(path):
--            os.chmod(path, 0700)
-+            os.chmod(path, 0o700)
-             for name in os.listdir(path):
-                 rmrf(os.path.join(path,name))
-             os.rmdir(path)
-@@ -43,7 +43,7 @@
- if os.getuid() == 0:
-     fatal("These tests are not suitable for running as root.")
- 
--os.umask(022)                           # for consistent permissions
-+os.umask(0o22)                           # for consistent permissions
- failed = 0
- protocols = ['2', '3', '4', '5', '6', '7']
- dir = 'tests'
-@@ -120,7 +120,7 @@
-                         errors.append("EXPECTED[%d]: %s" % (n + 1, expected))
-                         errors.append("     GOT[%d]: %s" % (n + 1, got))
-                 except:
--                    print "\n\nPossible invalid regexp:\n%s\n" % expected
-+                    print("\n\nPossible invalid regexp:\n%s\n" % expected)
-                     raise
-             else:
-                 if expected != got:
-@@ -145,12 +145,12 @@
-             sys.stderr.write("passed\n")
- 
- if failed:
--    print "%d tests failed" % failed
-+    print("%d tests failed" % failed)
-     sys.exit(1)
- else:
-     os.chdir("/")
-     rmrf(os.path.join(builddir, ',testroot'))
--    print "OK"
-+    print("OK")
- 
- # Local Variables:
- # mode:python
diff --git a/debian/patches/README b/debian/patches/README
deleted file mode 100644
index 80c1584..0000000
--- a/debian/patches/README
+++ /dev/null
@@ -1,3 +0,0 @@
-0xxx: Grabbed from upstream development.
-1xxx: Possibly relevant for upstream adoption.
-2xxx: Only relevant for official Debian release.
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index ec0fa51..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1 +0,0 @@
-1001_python3.patch
diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc
new file mode 100644
index 0000000..0ed4846
--- /dev/null
+++ b/debian/upstream/signing-key.asc
@@ -0,0 +1,284 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQENBEvSp5oBCACpVQe+NLiM90Y+c03CiRXUAK1NhmxcEefNLa18Layt4qQYVe+r
+4PSkF4EGJJFpaRGKvTzSqabAtnscfn5rKn9HPx2zEibd+71h7sVwGzw+k0yL0Rzx
+KlbLZUq5OPIAOMh3WS1RnqAE9yFf/D0EhSQDsieZinfmxJfpo6iCTS4d6aYQ/L5j
+6+hfLyuNQtQxgAz8v319lLTDG6uhFKbcRfVPvM5mHsKDtN0fZksCedxall6qMbeN
+ib5alV/492zok8m+kvnhz+GpcMwujo6MFwRFWLgzVQMyDO8s7i06rz8WOHxoaQOn
+4F+R7VsVfiYaoy8NDMt21al26pBLWT44xjnxABEBAAG0O1JpY2hhcmQgS2V0dGxl
+d2VsbCAoZGF5LXRvLWRheSB1c2FnZSkgPHJqa0BncmVlbmVuZC5vcmcudWs+iQFR
+BBMBCAA7AhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAhkBFiEEkAaw7XENuBt2
+02jZ0ziLoYp0G+8FAl5dhJsACgkQ0ziLoYp0G+/40QgAm4I+MnYz++Bjb+L+zOqW
+hcjLSwioy/UbfNKQyvLeLJzrusMfNXNjuemDSwK7Ht+P2unOotowbib1+hmYSAP5
+9LDqvFJ++eEvMSLlRnhVz8F+0owANASiFYZcuw9jWXw+DVLzlOHSyl1wdyhs/quP
+pGU6H8dQiPIy3Md1o/EpG2aOEM6DYrj7JsQYGRUuBXHWJ6FxZ0Y5ui4NVP69zPjy
+q1KUcbk/6MRsG78ywIuT3P1dCyNda48qhCCMnrjqAHWp5hNnMx9sbtU+4nARQMRj
+QMOztcNn2OWp7EnIdY2sSmSw1nbRNECOoPM1FW74VdqVQIum7zrkkKzk6z+8CkBE
+J7QoUmljaGFyZCBLZXR0bGV3ZWxsIDxyamtAZ3JlZW5lbmQub3JnLnVrPokBTgQT
+AQgAOAIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgBYhBJAGsO1xDbgbdtNo2dM4
+i6GKdBvvBQJeXYSbAAoJENM4i6GKdBvv4mQIAJX5EYkE5C/R2fdJxonZaWJkQxAl
+O67skqR2+JKCxELtmE1/S7hBZssJzVMU7VBBSyGnzGWp4L4tCHHl8sQDYG8ketnv
+rTAqqOAQQMSm4lQux0wOQQuh3cg/3fQLdwDCwOpWzIUB1TgPOxRzYn84WFcq1ErL
+YDEiYdpZ6PL9nZeZ0txfaX+Guv7qHToF1EUKY+67ladlpBy6jlMRPsRkyjhyAyBa
+x1GkSRSILDGHv3vVT/buVbL3mznp902t6QXJr3DnvuCENXbKWNDzhDwszMlhYOrs
+89E0uYoAtofEEoB2BUHtM7qI0YNE1VaDwXneSaX4OMiUaekvGqWlFXdrwje0MlJp
+Y2hhcmQgS2V0dGxld2VsbCA8cmljaGFyZEBzZmVyZS5ncmVlbmVuZC5vcmcudWs+
+iQFOBDABCAA4BQJZHwaxMR0gc2ZlcmUuZ3JlZW5lbmQub3JnLnVrIG1haWwgZG9t
+YWluIGlzIGdvaW5nIGF3YXkACgkQ0ziLoYp0G+8Vxwf+I2yhHdR1idOfyG6qpwCH
+SNvCSBTmgAlY711+W649zLv/7gKsRAM+Ea4S99nMq337skIcAHWaBoEmzzociXXe
+9VYyhdqowgJPTRVKrCypO0qjFVYfcl84Wn2PdXRMV+9qh5KkP+Fi0qOETylK1bqi
+WVlvKSHI9ngbxP+34kpbd6n6WzgnrrRWpJkRqhJwV5Q6EmsuOX19Mm1hHl26NwV7
+dgzXkZAJ8HJ0mhKObHo/q1wlZin9nr15uGP1ROmdVi46GbenRwSaoyxR+LjkFDGQ
+Ww627jKPrzxN77JLPWrRqznsTMG49lCgHlc6unyIn1vCCsc/Rvkwl1aTBuxELpUA
+ErQoUmljaGFyZCBLZXR0bGV3ZWxsIDxyamtAdGVycmFyYXEub3JnLnVrPokBTgQT
+AQgAOAIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgBYhBJAGsO1xDbgbdtNo2dM4
+i6GKdBvvBQJeXYSbAAoJENM4i6GKdBvvk5IH/07rIIgc4PC7ceRxTIOpPU/pVlhD
+aiibpOInk3SQNSnokbMHfdrq2Jo0GTYqawxIxKser4I4oILzbFJ9E5Gm/9Eay2W4
+wKnEZNnODpCFYA2I21oAaSSnOzBNnCPhkyGDjvtK7uQxg2239/gn03mjk0kAquv5
+bBsMbbacE0RBRHpM21eI+GEQyApQRnKfNq6BMrV9MfxTlaKyKLgCqc/2VXseRSQV
+ggPCQKOCRy6QR+y9h1MjooYkaeY67naKKDSekjJPNv8rzZQ5U2yFeasvJGltJCiw
+29Q3pkPBXkF/G0q1cSXqaKpL4q++xDrzf1ZROHk2I319Ru79Jo8ow/T2fbvR3nTe
+cgEQAAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgABAQEASABIAAD/4QJERXhpZgAA
+SUkqAAgAAAAKAA8BAgAIAAAAhgAAABABAgAJAAAAjgAAABIBAwABAAAAAQAAABoB
+BQABAAAAmAAAABsBBQABAAAAoAAAACgBAwABAAAAAgAAADEBAgAMAAAAqAAAADIB
+AgAUAAAAtAAAABMCAwABAAAAAQAAAGmHBAABAAAAyAAAAAAAAABTQU1TVU5HAFNN
+LU45MTBGAABIAAAAAQAAAEgAAAABAAAAR0lNUCAyLjguMTQAMjAxNTowNDoxOSAx
+NTozOToyMAARAJ2CBQABAAAAmgEAACKIAwABAAAAAgAAAACQBwAEAAAAMDIyMAOQ
+AgAUAAAAogEAAASQAgAUAAAAtgEAAAWSBQABAAAAygEAAAeSAwABAAAAAgAAAAqS
+BQABAAAA0gEAAHySBwBiAAAA2gEAAACgBwAEAAAAMDEwMAGgAwABAAAAAQAAAAKg
+BAABAAAA8AAAAAOgBAABAAAAIAEAAAKkAwABAAAAAAAAAAOkAwABAAAAAAAAAAWk
+AwABAAAAFgAAAAakAwABAAAAAgAAAAAAAAC+AAAAZAAAADIwMTU6MDQ6MTkgMTU6
+MjA6NDAAMjAxNTowNDoxOSAxNToyMDo0MAC5AAAAZAAAAKAAAABkAAAABwABAAcA
+BAAAADAxMDACAAQAAQAAAAAgAQAMAAQAAQAAAAAAAAAQAAUAAQAAAFoAAABAAAQA
+AQAAAAAAAABQAAQAAQAAAAEAAAAAAQMAAQAAAAAAAAAAAAAAAAAAAAAAAAD/4QcB
+aHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49J++7
+vycgaWQ9J1c1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCc/Pgo8eDp4bXBtZXRhIHht
+bG5zOng9J2Fkb2JlOm5zOm1ldGEvJz4KPHJkZjpSREYgeG1sbnM6cmRmPSdodHRw
+Oi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjJz4KCiA8cmRm
+OkRlc2NyaXB0aW9uIHhtbG5zOmV4aWY9J2h0dHA6Ly9ucy5hZG9iZS5jb20vZXhp
+Zi8xLjAvJz4KICA8ZXhpZjpJbWFnZVdpZHRoPjI1NjA8L2V4aWY6SW1hZ2VXaWR0
+aD4KICA8ZXhpZjpJbWFnZUxlbmd0aD4xNDQwPC9leGlmOkltYWdlTGVuZ3RoPgog
+IDxleGlmOk1ha2U+U0FNU1VORzwvZXhpZjpNYWtlPgogIDxleGlmOk1vZGVsPlNN
+LU45MTBGPC9leGlmOk1vZGVsPgogIDxleGlmOk9yaWVudGF0aW9uPkxlZnQtYm90
+dG9tPC9leGlmOk9yaWVudGF0aW9uPgogIDxleGlmOlhSZXNvbHV0aW9uPjcyPC9l
+eGlmOlhSZXNvbHV0aW9uPgogIDxleGlmOllSZXNvbHV0aW9uPjcyPC9leGlmOllS
+ZXNvbHV0aW9uPgogIDxleGlmOlJlc29sdXRpb25Vbml0PkluY2g8L2V4aWY6UmVz
+b2x1dGlvblVuaXQ+CiAgPGV4aWY6U29mdHdhcmU+TjkxMEZYWFUxQU5LNDwvZXhp
+ZjpTb2Z0d2FyZT4KICA8ZXhpZjpEYXRlVGltZT4yMDE1OjA0OjE5IDE1OjIwOjQw
+PC9leGlmOkRhdGVUaW1lPgogIDxleGlmOllDYkNyUG9zaXRpb25pbmc+Q2VudGVy
+ZWQ8L2V4aWY6WUNiQ3JQb3NpdGlvbmluZz4KICA8ZXhpZjpGTnVtYmVyPmYvMS45
+PC9leGlmOkZOdW1iZXI+CiAgPGV4aWY6RXhwb3N1cmVQcm9ncmFtPk5vcm1hbCBw
+cm9ncmFtPC9leGlmOkV4cG9zdXJlUHJvZ3JhbT4KICA8ZXhpZjpFeGlmVmVyc2lv
+bj5FeGlmIFZlcnNpb24gMi4yPC9leGlmOkV4aWZWZXJzaW9uPgogIDxleGlmOkRh
+dGVUaW1lT3JpZ2luYWw+MjAxNTowNDoxOSAxNToyMDo0MDwvZXhpZjpEYXRlVGlt
+ZU9yaWdpbmFsPgogIDxleGlmOkRhdGVUaW1lRGlnaXRpemVkPjIwMTU6MDQ6MTkg
+MTU6MjA6NDA8L2V4aWY6RGF0ZVRpbWVEaWdpdGl6ZWQ+CiAgPGV4aWY6TWF4QXBl
+cnR1cmVWYWx1ZT4xLjg1IEVWIChmLzEuOSk8L2V4aWY6TWF4QXBlcnR1cmVWYWx1
+ZT4KICA8ZXhpZjpNZXRlcmluZ01vZGU+Q2VudGVyLXdlaWdodGVkIGF2ZXJhZ2U8
+L2V4aWY6TWV0ZXJpbmdNb2RlPgogIDxleGlmOkZvY2FsTGVuZ3RoPjEuNiBtbTwv
+ZXhpZjpGb2NhbExlbmd0aD4KICA8ZXhpZjpNYWtlck5vdGU+OTggYnl0ZXMgdW5k
+ZWZpbmVkIGRhdGE8L2V4aWY6TWFrZXJOb3RlPgogIDxleGlmOkZsYXNoUGl4VmVy
+c2lvbj5GbGFzaFBpeCBWZXJzaW9uIDEuMDwvZXhpZjpGbGFzaFBpeFZlcnNpb24+
+CiAgPGV4aWY6Q29sb3JTcGFjZT5zUkdCPC9leGlmOkNvbG9yU3BhY2U+CiAgPGV4
+aWY6UGl4ZWxYRGltZW5zaW9uPjI1NjA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgog
+IDxleGlmOlBpeGVsWURpbWVuc2lvbj4xNDQwPC9leGlmOlBpeGVsWURpbWVuc2lv
+bj4KICA8ZXhpZjpFeHBvc3VyZU1vZGU+QXV0byBleHBvc3VyZTwvZXhpZjpFeHBv
+c3VyZU1vZGU+CiAgPGV4aWY6V2hpdGVCYWxhbmNlPkF1dG8gd2hpdGUgYmFsYW5j
+ZTwvZXhpZjpXaGl0ZUJhbGFuY2U+CiAgPGV4aWY6Rm9jYWxMZW5ndGhJbjM1bW1G
+aWxtPjIyPC9leGlmOkZvY2FsTGVuZ3RoSW4zNW1tRmlsbT4KICA8ZXhpZjpTY2Vu
+ZUNhcHR1cmVUeXBlPlBvcnRyYWl0PC9leGlmOlNjZW5lQ2FwdHVyZVR5cGU+CiA8
+L3JkZjpEZXNjcmlwdGlvbj4KCjwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cjw/eHBh
+Y2tldCBlbmQ9J3InPz4K/9sAQwATDQ4RDgwTEQ8RFRQTFx0wHx0aGh06KiwjMEU9
+SUdEPUNBTFZtXUxRaFJBQ1+CYGhxdXt8e0pchpCFd49teHt2/9sAQwEUFRUdGR04
+Hx84dk9DT3Z2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2
+dnZ2dnZ2dnZ2/8IAEQgBIADwAwESAAIRAQMRAf/EABkAAAMBAQEAAAAAAAAAAAAA
+AAABAgMEBf/EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB9AAA
+AAAABDyNOWt/HPR8s9Tyj0vNOzjjp5zs4j0fNPd8Svf4Dv5DrwjdDAAAAABMAAAA
+AEHIZ+cXmaZl5AimKQRVDzKYNSQk2xPb8o93zz0s00AAAAAAAAAzOXzhIQTZKJsg
+KRSBFom5ShISJmm4ZWknocR7Xmnr8x1JGAAAAE8RxYKmiCoLgoKgVyqyLM9B6qut
+efsXg7jzu9PL6k5NUVEMh1Njk9zkPRzTQAAEjycVyUQWNQaLPc1xetHleycfcvB6
+B5vpHB3nN1k3U0TUZarx9J5u6cjszTLqkidD0Q6LGIwAzZ4AsNJcrtX1TWzWyLVU
+igGAMpoYMgADPQ5eg8Xe4xpM1Qj0ZPQk0EYATkvkhiQM6bm9HLQU6oGFAwAZQDBo
+ahoaQF5tk8l3MtM9iqr0UbCMAOS18ZxAMXsJrTE6OU7OY6uI7OI9DkXuwOiDWQxN
+OcvA6Mk6MjbA6uY6RfP1Tgdzoi5O2LPQEYAZ855YsVEB2KbjUuTp4bO3hTrzVzNU
+jpDVmdGUCq5OY7cjq5pddFizkE4Vc6IYerVmogAHJseM1hEKO2pvWlw3MtUw6LJa
+5aS5s1S9KRMx2Ofos5+gjUz1hMEvG7POGdGaUejrYCAATR43WeW1zDvM73FtgxoE
+ZpYDSzUpAwsSkNDBOIDkVnBTOvau21yCAAAAYanldJ5Gi9KzvqS6IoVgmZIkOgNG
+SgDRVQgwACSOOq5+1L2uAQAAAABoZXB1y+Ved6pdEWDFSMWY2UjpzDRFpVBSKQwB
+JQSaO5sZEAAAAAANDRzarxTnepLSGqUiQ0uslM0guUvM2xN0WkCpR5/p3FtAExAM
+QAAAAADPL3m81nWklMw1Obdc9BVaUFk6pnqmGwmWkc1V3NDIAgAAAAAAAAABNfM7
+ZrjiXfONZWpKAdoyhLkqUaHJWZpVzs7lAAgAAAAAAAAAAAA49Jrhma2zNpNZXVAi
+5SpKkrOwaujRXPQMoBAAAAxAAAAAAAABjcvlVNy4GUquV0kuUqRhVVTQYg6sbnZo
+mSxMTBn/xAAlEAABAwMEAgMBAQAAAAAAAAABAAIRAxAgEiEwMTJABBNBIjP/2gAI
+AQEAAQUC4iQEa7QvvanVwvvJRqFCuhWTTPGeElOrAJ7tRnIlNqFqZ8iUawCbUn0K
+leFqJsVKB31KcpTXaSx+08tV+xUoFOKFo4Q/alUlA8dWpCkuwji/b0quwdwuMCo/
+U685xaVNhaU0ptWEyoDmVWfrdgLxaFGzWyNC0LQi28LqzCQmnL5LtrziLdmExu0K
+EQnNURYr9i1OdLcCvkbvsLAKCg0lMpJ1Er6nIMhNYouQi1aV1c9Jng3Ap5l2DWID
+jITxBd3Y72p9YO6d3YJolDlIRYunnsqVSO2Dtw7uwbKY2OcqqIcnIJiBwKqiH2aP
+RqtkC37TP9NwcVVMus30SnjfuzEw4VEbBNtKlStSlDCV9i1rWtam1UboWYcKvgbD
+sIm26M2BTSpsUd1pWhaCoKBi1bpC1KcHeKKHf4EBb+VLVsghckBfYhVCFQFdotQV
+fxvSENvXdtf8ARdCdK2QZLIgptinLT/O6azcShvav4WCZ43rCxszpEbkSA3adrNu
+RbSCgNoQtX8bNVPxu8S09WZ0oUKFCizcIWlQovX8RZjdTsCqwg2Z1ibN4q/SaJTG
+6cvkN/mNk3oYmw4q/Te6bYzreL2xZnQxNhxVUxv9NGZEh7HJzS00/HE9ymmxMKQc
+3iXNbHF8hkpuRR3TSpRbKAzCHE8SogjAo2A4SpADdxxVmiBmF+5lMp63cb92DAqV
+KBUqVK1BB2LWxy9FCxatKhQoK0rStKhC7e+Ws3cIZTmUBA5SJHicxk3c89RmscrO
+/QrhDjCZ36FfwQOc2Fm+XoVP87ytS1LUpyG/oP8AC8KMRgw5/wD/xAAcEQACAwAD
+AQAAAAAAAAAAAAABEQAwQBBQYCD/2gAIAQMBAT8B9SouVFiUUXVkeMccf248iiit
+PQGodiTWKVFFkBwG93HCLThGX//EABYRAAMAAAAAAAAAAAAAAAAAABFggP/aAAgB
+AgEBPwGygpf/xAAkEAAABgEEAgMBAAAAAAAAAAAAAREhMEAgAhAxUGCBEkFhcf/a
+AAgBAQAGPwKJ9225sqcDB6SaQ8xd8mqJTvctdQg1dVmcNtwH6ku5XArbwt3Z3jvJ
+mQQ1C5mgb2PUBYEeaGEVqReAr4S9NY37Jfuk8hyc00g5rfK8hhDvft8j7w72r+TJ
+n//EACUQAAICAgICAgIDAQAAAAAAAAABESEQMSBBUXEwYUCBkaGx4f/aAAgBAQAB
+PyH4JGJZZI1Tb9CZ5Qj2Y9ChRypjGoiWI05ErT+NK+BsSmIKTn7GbAp0No0jfSP3
+eKR/ahDpVY62hBT5vm2ToJfkd1pJf7NLtjb/AIUF5Ie8Jo6o+mQp7J+kf0HJumIm
+kUuTN8WxSZJ2NcmmhnQzS/ZUhTIxEkUSf79lnd4kYkU0hspcxyWLXBkWNDYbY5em
+R0hKFIx7xQidpHYmy/sa+hvBWf0bhoQ9Cc/AvqBjPAqVm9aHS8LxhFWPYsTAk1hf
+mD2Y08DEnZEawYnKHtgU8Pg8IbAqCLwjYneIEIHkQyyzExKhKoZoLa9dCtDSSjlC
+rt7EHQnLG0ySN0iaNkIslToScA+iIVxZpLiwjcGj+tjQdGX6KiN6GnhRDr0GkNya
+YYx+NnRMgQlf5IBwdn6IUCCMm7NH+BakW0+8ETBGKKcNSbGQIgUhBAkQQQJcIwM0
+E3pRbZC7f6G8KIlJGhUlkXDcNbDIIkJeRBfJKKjyRJ7FktoknTKS6E+CyoS41mJv
+2IWF8iNTyOP5w3LwTOrhqS3gYkVCwvleD8A1K+xKlEQ04bxDumFs0EIWZEPMkk8F
+oicTETT2OlsoUOVl6FnX7LORm5oIgJSKEmDneGxlohKyAkFIZFIVDD9kEVfBLvpm
+w9j0NDwibfR6jdyWN7wqw3QzJCboT+cDVsmCcrB3kjP98O9qB23g4mCsvGoG+zQ/
+pGuhthA1iIJ6PDNWVpgWChZ1I90ITwij7GoGaYrwtVHaexNqJTv6FI0YwLfASWR8
+yCIusREhTk6+gyOJ9MoIxdicI2L8CdIdobzsgkSyYgBlidtDhBUkbcu8Nh4E2iRa
+sjhpEBIx/udCEWhI/m4TiEu2PR2axcRoM2FrEESHG1ezYSocpddi4qbp2PQjSLKQ
+80OsIXB40+xbH1RC88bJHhaG37HZr4nh2LlC4s0iTAUFy0rpsWsM7NPNWxSBiFxZ
+1FuRdK1znk+yFTWrIA017NAhcRomUYTsgWoIXBjFeIF+wvhiJVaFhCELDHuT+Y6+
+xUEPIg0Li8Ev4obXQ6DwQsNhBaIWhCwuBzTY1mvlGIRIxkCUQIwnhcHY/LFSiPjX
+Q6HwsMR4HPH6AhumJ5alwJvcv5Yn8BaNBoQ9ldCU92Ii+zwSoq64e35okTumMPho
+jEiCYsNCw3zwpyKY03gmJ8VySL+A+gaLThiZJIiMLg2TL/CkqBb2MJiYsSLLY2J+
+EpKfTyJiE8SSMNiYeE/BWcicCKECGSsWNDQT/A/sBawlghBGEhOENsRiM//aAAwD
+AQACAAMAAAAQ/wD/AP8A/wAwyAG7c1Xf/wD/AP8A8/8A/wD/AP1VXZkZVUDITvv/
+APN//wB5mdmZEZ0qasoAiK/7/wD5TRVdWv8AcRjBnyYMjHP/ALjpu4u6Iiud+kOK
+zMyL/wC8EkLD3eqoSO5oqWDMJ/8ARCcKaZ+/8czOZycX+Qf3wm6ZU/8AI7O+6zf6
+reqH/wDUqyTVtYm3nFCVhOmOB/8AEAIgypAFh7rUC/aO6g//ALdAsRk/DKjMgEim
+Qaj/AP8A97jl3AhZtvsFhArNn/8A/wD3EixRCMDO+ZBMFVw3/wD/AP8AdxWzndSc
+b/YjlNt7+/8A/wD/ALWnN+NEiryLALN//wD/AP8A/wD2SXJzRLZ6Irvz/wD/AP8A
+/wD/AP8AMgFUKj+hiBc3/wD7/wD/AP8A/wDzl7VAl+Rb7bO/8//EABwRAAMAAwEB
+AQAAAAAAAAAAAAABERAgMEAxYP/aAAgBAwEBPxD8bCedIhCCwQmDE8CQsuEITdoa
+7JCXsEhLwtDROSxSlKXq+aFlosFueBPR9FloQJCE2i4HxWYQnCEJlkEiLwXU93EN
+3ihcKUpS7WFObC2hNBNWxvxlxSlLo2N3RpSlKUpSl8pvc+uzW/8A/8QAGxEAAwEB
+AQEBAAAAAAAAAAAAAAERQDAgEGD/2gAIAQIBAT8Q5UpSlKUpfy98UuKlLqpcCfV4
+rze9/YQa9whMD+plLpe1jyLix85jaHxpSlxNYEu7E6rC9z7X3//EACgQAQACAgED
+BAIDAQEBAAAAAAEAESExQRBRYSBxgZEwobHB8NHx4f/aAAgBAQABPxD8CCJ4qvMU
+DDuxoyMCFlneJ39VJdDfdmWW53iyEl5t1LtIvvxCqXS/wg/gVzGn4WKT3VEKrdXx
+4CGEsHNzikFTT5iZZP1BMY9mYopeGNg77wpe8hmfAaZQBnw6hxm7lh69H1gFwGBT
+s4PjmJKVz4gi/bMRo9iyKWtXyuUoAUb4i1WWrZiKXgOxAAu86IBlazQ95h2OeeIH
+UzvgqYKlB4jaq24lILV9xDtgvMMerRggs9IEBpYmaqXUQHa3/anCB2olC5t7v1Ch
+UsfMsBxTcA3g7EEmiiVyDWfvX+94UK2XAd6phG/+xthxeI4rC1Z24h3ahYQltO+Z
+U/fHMuB4YN+jSCgehURnFU5vbGAaXlqiBMFG1vEypFodG4iWzVH++JY7uLW1vvB8
+v/ZaytvYxFbgDZjiIXUyX/viAqNcwRho/bK4H0iZsfcJWNruNLQytC9OWFF0K87h
+CT2Y4/1zfFPaD1On0qkoZYxa4VKUUuslxzrAZexBmcmobKftlMk6zAwl4/UQ837Q
+sL54li43mFG3lxFRj3Igu0Dv/wCxuqeZd3zBF2rxL5rEsGQ96iJBNyqtOcmozhq4
+CdNPRfvBFSHWcXLA4fPE3dvMCU5/9m1qVV+3H9TPc1qNZxgdd4Jbc3mBwwtw3F20
+EMF4upRNZ17QHEvxVxIge0qZyy/YHSSjW/hIGijtlBlukgYLVy4037wbI9WOQGd7
+47fN/qLNDLzEWpteYVbrad4pWy/qGgSmo23FbO4YGMBFRpfeUpLLrOIBFw1MgbTv
+KJ0YdQnSIiqsY2qo5WIfDmpmg5/gjBQs71K9V5Hiqg0NAxdyrNm0YYu3oUAIYpTF
+tvA8G5YXvFS4XEyTQisHm4PEXKdfEcHJqAswN2YC0HnbB6tfeNYAVo4hCpSJhpLr
+3e4djYym3cY8zetN4ed/3Mrl0M8CrmUE8F0d1/36m80Kf3uWcpxRBpdxeqpU58x1
+8XQMyK33YouFWAos0f3KhrMJwQOKIHRQ4m2oEqBEjFnEWVYe00rAQpHMrtqOzb/8
+1EAWA4D/AHv9wSFUf3N3FMJAOvRxsqQCrvFXGoO0AF8xXNsvwXn+JQEMINQ6EHoM
+OiXC3m5IWQKqM5mlFqU6FvHaH6gj2SrYZVx6AsqsSMGgUupQHdmpQKPdgFC1tiqO
+HQdToQ6pBZHIYaTJeE07XMM18wDVxZQkYKKnPMsyPkmOotYGKBEw54qWtDmDglQx
+DUOkYQ6OIQIHW5cFy1rfERbu1/vqYw04eYhgFUMYh0oNSqOrqEAch2jklBV6iN/M
+d4QtF6NIYQYQ7m1QMTXody+lzlWrF3CGcNbI1geCRGzrbXEuIKOuSjisClRFmG2Y
+0G2DAmBIoEbjOYgtY5lbl8u3LlbKxzHK3OaYQS5hGxhsl4OY1NP3D0mN1AA0s5jI
+taF+8LrPRLJeItKvkgyPM7nQsIxUotyl0w5wiQHVjFt8MSxqbE4EvQFHSYj60gWq
+mlRS3BvNQ4vmVg6vEwX2dS7LHMFXaVVviF10Ywo3sI8DAaPEzt8sxY5viJyEKskp
+M0Qn9icRhmWfEe3MN1c1h3mA5+icpaLzFcprEE8oC6ldOIrHtKD4g6fmKwaX/MFx
+ylsDoxBwu74i2OTcFNMDJ2mLiZbjj9lSrLDiQEod22MD93cyL0Ydx6lO2JcEVhDX
+SIW0cxowWUDVDUDT2+o6pAPY8fPf3jBaQdC7jSY/OW/KcJiMqgtNyijOKh0Wtkwy
+pZfeUC1SuYMngIrjvBae0MJSZIBssyJxGCgOmX3KDGKI57Et294lJNRDUzl3E0JL
+JG3mpSWB4JxBiUI6muN07TOr5gnyJyik26szdxMqavDFdnmGfnBl8dDaDmsb7iDN
+44UMo7l3E8UKahSOIsFk8wqqyh9iZ5GygrAAGA9BKZdDNuHbX/JcPgqAuYD46QxA
+gSlRZjuZoRzNui4PQRxPrWmf8mI7IYlir6/2fv0tjVwzBwt15r9TIZr+UDXUf0nS
+dLmk3hnojUcTLqIR1DMw8xaBlxKQqs3ddp/j6XiBaDREO0pDW8n6njNM4IsEGEqO
+pvDFxCBiWHoMyoRmsopeziGEoeIpYolB3/1T49R8ab7RNEmFt/HEsLNlM1Hfhsji
+h0ekDLBeIVIJVwawHdahFsTxNeqozWGdNP2g5Qqgo9dsq9kBZspe5Lo8zWbdSqMV
+ZlOKdzMVnCLBLJUJVrBRBh0Y8QF3Nqfv8BE50R3DI1HqbdGjoG4yTaYNQQQi6Lox
+YlZR4vLK2ikun8V3AEaIe5HjoUbRzLqg3SFCa6A3F1feIhhVoO/mCgADBPj8Oe8r
+aFy+s9AcTSagm0J22/aFtEYandBIgMkT2D2uYMPtLulxiCi8nEswrYvMu+jv8KCI
+ljsi1uSRRlGLEdaW+ZVdk7ZH3hiJd9xnP6IFZf5gXBOCuJvFS2JcWWVS6i+pgvPq
+QRj7H+/iWE2EcksjJZxA9oHZjOiCVAYaZc4SYh27/NcQCb4jXnzMuJaS+lEogCIg
+y4sWNTzNzxmVjcr82dKAy7+JagpNjMcIItBSum5cWUTQgz8Eej6TX4WqRSI5lLT0
+O50mo5RdaiIsoLZ/FH89ksQ6X9JB4ZRhgJH2mGLbCk3gktl2XU3PcGJfiPpN/hS5
+7dB/cSy4RYQindg3DCjTFuipfeFXiCiiBLUJsgickfSbl/hF/wCjEFhlVLYQnaD7
+SxKnc6AdHUsdzUq5aUwipU//2YkBTgQTAQgAOAIbAwULCQgHAwUVCgkICwUWAgMB
+AAIeAQIXgBYhBJAGsO1xDbgbdtNo2dM4i6GKdBvvBQJeXYSbAAoJENM4i6GKdBvv
+8UYH/2VFY6N3o4pX83Wff5ArpqkN5w8mgArNRMpUE8M5jsKzFwt5zYbTjb9/jamz
+5sNVuKdguu2459xOMigFmu5lpZ1/kUw0PuHx68TgV3Jbf/ADcPfbjek7vDRrvNyC
+/R8J9PSbtGDjbjEXwEuSG4ZygaTvshrB4udjs8Vw5Jrha5kOGMcFoaZNkjd8frEh
+R4XsyIpUn2ES2h85iLHW3dgRQEaqDf0ZAk8lRiwjQZO3YOVNxzJCdzgsNBhDWkwg
+kt8EIPsmKL52vLw1LgmnINbPD3mEeQambEQmafkL7ApmNAfIun1xrYkPF5DU5KDD
+fmlkGc93ts3Bdjbu3m/mfEtHsfS0JVJpY2hhcmQgS2V0dGxld2VsbCA8ZXd4cmpr
+QGdtYWlsLmNvbT6JAU4EEwEIADgCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AW
+IQSQBrDtcQ24G3bTaNnTOIuhinQb7wUCXl2EmwAKCRDTOIuhinQb70GfB/9JyzVy
+GY9H7wICQdESB+wywlK16MP4aOYGoqQb7igcFqHliKTcdeXqQ/ikD1gHCMZjAOLi
+/2/GfsUzHf8txR8+LLGjfyIZ+95EK4tvxdLZ/Bd0y4zH74pFNsSK6kfWtpofw4Zn
+op6OtfIQA2lQ9e4KZIZyh33X1ntcxccgpJYwgKLbUI3sK7S8JOOM+u8IvDLkPSOm
+tkRRR7ajPHgsiDNo6EiHhsmpGiDs1DengSh3JfyVtGR5DY17EPf8pO7bvZmaCosv
+lRbUvJgxvSdkcizyCCaTYyqmd05z4vODFiHZwdArl4ypZeWlPV0YhVg0J/BJiy+m
+FeHy5kVzhHWBhWiatCZSaWNoYXJkIEtldHRsZXdlbGwgPGV3eHJqa0BpY2xvdWQu
+Y29tPokBTgQTAQgAOAIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgBYhBJAGsO1x
+DbgbdtNo2dM4i6GKdBvvBQJeXYSbAAoJENM4i6GKdBvveh4IAJLzQqwZQdPFVXTz
+urg061zeV77NxIZEWb2lWhh/v/9X7ONAtjk+0HzrJgIGZc7ZzIVzQwsqze5us9cI
+2qd/V5qe8uQXZ1Z5iraDZ21s3IsdZ51jWFotkGqtwF1kRWy0qnTGybRbU/61tSRy
+1SzUe5pCqr9HPMOwUHh5reBfEgNs2z07OXTACJV5Iqs6OhL5r9aILCrxPxEoqa4G
+MEEvkNfznSNQQFTr/LKSQIYn/S+o3ZcXLZXJ+bA2q0jAlmblMViOXeNZYuqDI6AT
+rzjvdVMoATQhWmR/mWtPEmNtpNOcj2N3PlYfp91ms2yvNilZpZ1HFvcyQ4UR6WKv
+2si7kme0J1JpY2hhcmQgS2V0dGxld2VsbCA8ZXd4cmprQG91dGxvb2suY29tPokB
+TgQTAQgAOAIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgBYhBJAGsO1xDbgbdtNo
+2dM4i6GKdBvvBQJeXYSbAAoJENM4i6GKdBvv+cAH/RU71BehFtL6JaWFx5E56bXs
+eQW/WeivW5VZ4Sczmp88NBfb9WLuJ3CFW57BjmVHE93++YlPlQnaQ9H1KzEw+GXa
+nGRPKZ55AZ3WwGqkH8AjCbQ2tSTn4ab6X6n1Lo2MmDth7eHm/LphfHFPqAz9Pfyo
+LOwcazXzYsBNYOKm1vG1dQ9R8zV0sRQbfOfjROye1Uzz3jCtN8icuIW1gLnETIDl
+IpT5OsNDQ2XrV5f6xqHUkWX6+kNvW53H4ooqgjett1ltF720HzudH6ozq5Xkwyic
+Q36WPc2K/KgoJz36bvnFqJLxbyac841qBK88fd3YMh0dBRhAQDuJ5OWMX4i4HYe0
+KFJpY2hhcmQgS2V0dGxld2VsbCA8cmprMTAwMkB5YWhvby5jby51az6JAU4EEwEI
+ADgCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AWIQSQBrDtcQ24G3bTaNnTOIuh
+inQb7wUCXl2EmwAKCRDTOIuhinQb77wLB/9r/BT/tTmlRhfyVut5P+Jkjt2uliPv
+TS/Pwc0Ltvi4u1gY7ah/0B9F49uLq1qXhVl0GKiF2eybhsVOfdFIYXxnit8FLHpl
+qEU8BK7x4Ai4gGdOQWnqpbAHfJiJ8Rc4odomLzOHyzAyCWBbKgpY1zNbeyWWFa02
+It7CfuRzAOZpRv0VeC7c6rZHWGiw5sA2QrNs3bscRCbchGGBE6j1CvuGGfGVUqMQ
+Y+n+hR7U/HSUQ8gGWLItBWMWwTBZ4rJhYJgRexlOn2DNtD4zcav0Dl3yMzDax6Sj
+6+J2rsmR+E+vnQwDY/0OPrtGIvspywKSYQRPdR+iNg8KX+671V+qNYx+tCRSaWNo
+YXJkIEtldHRsZXdlbGwgPHJqa0B0ZXJyYXJhcS51az6JAU4EEwEIADgCGwMFCwkI
+BwMFFQoJCAsFFgIDAQACHgECF4AWIQSQBrDtcQ24G3bTaNnTOIuhinQb7wUCXl2E
+mwAKCRDTOIuhinQb7ym6CACKHhH7tGycqt0tN3SmJ8HfcWqt10rqC7/heC+05Cgh
+qbYz3/IT5fpXvpI/rGKKfYI4RdnFVtnGu5ltVUO8e9e4SVof6FljYPYl6OnfeT1V
+Epm4CVfqqPJ7Kn0dUnhJ8bICc9W3qh0opNVo7HGzM8RBKGzRUFeUEy9udmiZ2jme
+naj2skFJGb+Zimg7pA0n8iT6Hqncnwm9Sb0qRTDR2sXW+Ww9FHmRwzkrZu1bfOC+
+ud1h8BpKMF9PqvyeX5b8G02FdrySP5DohmySAhopOwiEP0K54GHmOxvvmfaOoS0g
+MSANRCnlQqHR1VzN7s+Nj3pba4gC7Iu4RDofHZOpaMliuQINBEvSqEMQCACMtD5A
+3xwXNiav8qktQhPZYK6jvpCYa7JXbRhZFzUuSmp/xHT2pRB0k9KCNr4htLxE4z0a
+TU5c2fH2et2FG3lJhQ5GYZTDmzlCtCh4xvWcGA7sADd1jRAWDYhyWaYVM/587GcG
+6397oreJr99dW5o0E0GIGd895CHQot8RO5g/ZHq4u12DTSJ/mwL+s2cORMXedMnP
+FKX8uvm6IZWgGnD6SU77nW/vTWa0gvOUOzj/+4Yx6QMniMF+bc5MVPG33vD05LFc
+wVOGOxpZOClFizIsbmHLOGRf+sOEoidKyJSToId+jpGawPFAm/x/e+X7ba1/fB1r
+Jn1dHZHpWLRGc2j7AAMFB/41ka2PTflKFbPzBT4QtOIM4ejwZcNeA9JocfnEDq3c
+QM0Dp7HKIf7/6+ULy/gUtyf+ZmWR2nHloU1fiD2SDErj6XQ3w+7qfdrHt/YpDaSf
+dleCOcydjm6agwCuYlnD8/+Nr4v5XD1bWvdaBdCSciizpwt05h8iVbTJDsrhHBhW
+EdxePUxQwVto+BVG2TLNgDiInK7DByN45lRfluDErqxthl324iIJxQS4IXkIZ5Wm
+j+YFwOKqozJtZp4kAS4cpNbekz3JhSxRDlTtGreSYKh7M/zf80OP9HejrojxaAIk
+7iakxZlTM7arjxAKsIxVhDxTlLkGLElON2iXFvMPV2CmiQEfBBgBCAAJBQJL0qhD
+AhsMAAoJENM4i6GKdBvvppAH/2SzHvTOomqhT1cC9OqGG4c5BsRBrmIHhRFeLxr+
+EtPi4NYYsOErshSIIsQAMR6Y8I0JiRl+/fdFwQsiH3BiZruTPLAsvwYDOjyYQrbx
+ozj4Z0iC8qDtahxw7hnRJVfiLY/bxdWTkI3dJPmYvyZdBw06ucnAzXfX3Jz38sow
+OvRDYMhliLWrf6bz0dl3hZNpbZIvZYbOtfCB/DA6JBtkImWUGc97mZHFx0qnHEdF
+LRWs4VGPASVX0piDkx0+eFKfk+UXReI0T98dWPueuRvb9ZuOqc9dJrEfw4ipttdU
+4TOyZE+d02m+pdaQ7yw5egkQHj5rmdtfvYtik57956YNYHq5AQ0ES9KoWwEIAMZ6
+/fEGCL1ohywjjWJfDAnmyycSrlBLoO1O5gU5+7WCvtsTbSs/z/opoSmXL+4lVNbR
+Ol60H3wMFbCSAtgRikliCQC8C61qLf8wEjfXJENDsaJBEX9M9Xskd6/bx+qr8fkt
+brFjBipqd5C9vL63QjwAFFflwjaKJsKjtMpkm7Om71vvS/vkz/tYpqVgoYIdDTHf
+y6PDuWq9Lf3xRj2EGi9nNRnAbRvZBEOcUVUtf2lU2kvKwnvJ22bZbAnXHGpZ922p
+crwZs3Te+y7u06w0zEnr3wvY2sAbLNVvKO8/vs6evECx9wrmEYsPXsDnZUBY2oFd
+YUXv1rmmI9SHc9bw+JUAEQEAAYkBHwQYAQgACQUCS9KoWwIbDAAKCRDTOIuhinQb
+77BxCACOEFI8PpPqOSkEEmQDOLn482MloVRoS0WVqW/aoNGPEE8Xeu/NZWjK5VyC
+PJzczNHrNN0XoFotDepQ7bDpbn4azxouY7OIncMGUZmg3EcvglMYtaOTDEUSC1Wn
+TOwFoMPxzgLiKdZG2IxecWeXwVcqyxyQs4hSQCWXt7G8OlCVOP/nbHtMMO0pyKop
+4bNtLyE+dE1Xpua62zNr2j4j+Lmq1Iuezzgt63L9P5MhroChV9ZmdnduUgpH2bTk
+c4/r0+7kAeepvkP06Io8GczAMn+VCqpuMp1kndWX/fL/qNge3ne/TcGirMfFPTYG
+kzFA37mlFKD4rUQPQ43O/EcqOAly
+=T5PZ
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/debian/watch b/debian/watch
index 699d756..faad1cf 100644
--- a/debian/watch
+++ b/debian/watch
@@ -3,5 +3,7 @@ version=4
 # update: gbp import-orig --upstream-vcs-tag=vX.Y.Z --uscan
 
 opts=\
-dversionmangle=s/[~+](dfsg|ds)\d*$//,repacksuffix=~ds \
+repacksuffix=~ds,\
+pgpmode=auto,\
+dversionmangle=auto \
 https://www.greenend.org.uk/rjk/sftpserver/sftpserver-@ANY_VERSION@@ARCHIVE_EXT@
diff --git a/debug.c b/debug.c
index 831a321..74c1325 100644
--- a/debug.c
+++ b/debug.c
@@ -45,7 +45,7 @@ static void opendebug(void) {
     if(sftp_debugpath) {
       int fd;
 
-      if((fd = open(sftp_debugpath, O_WRONLY|O_CREAT|O_TRUNC, 0600)) >= 0)
+      if((fd = open(sftp_debugpath, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0)
         debugfp = fdopen(fd, "w");
       else
         fprintf(stderr, "%s: %s\n", sftp_debugpath, strerror(errno));
@@ -66,7 +66,7 @@ void sftp_debug_hexdump(const void *ptr, size_t n) {
     output += sprintf(output, "%4lx ", (unsigned long)i);
     for(j = 0; j < 16; ++j)
       if(i + j < n)
-	output += sprintf(output, " %02x", p[i + j]);
+        output += sprintf(output, " %02x", p[i + j]);
       else {
         strcpy(output, "   ");
         output += 3;
@@ -75,7 +75,7 @@ void sftp_debug_hexdump(const void *ptr, size_t n) {
     output += 2;
     for(j = 0; j < 16; ++j)
       if(i + j < n)
-        *output++ = isprint(p[i + j]) ? p[i+j] : '.';
+        *output++ = isprint(p[i + j]) ? p[i + j] : '.';
     *output++ = '\n';
     *output = 0;
     fputs(buffer, debugfp);
diff --git a/debug.h b/debug.h
index 6e763ee..35175f0 100644
--- a/debug.h
+++ b/debug.h
@@ -21,7 +21,7 @@
 /** @file debug.h @brief Debug support interface */
 
 #ifndef DEBUG_H
-#define DEBUG_H
+#  define DEBUG_H
 
 /* Debug support */
 
@@ -45,7 +45,7 @@ void sftp_debug_hexdump(const void *ptr, size_t n);
  *
  * @ref sftp_debugging must be nonzero.
  */
-void sftp_debug_printf(const char *fmt, ...) attribute((format(printf,1,2)));
+void sftp_debug_printf(const char *fmt, ...) attribute((format(printf, 1, 2)));
 
 /** @brief Issue a debug message
  * @param x Parenthesized format string and arguments
@@ -56,10 +56,11 @@ void sftp_debug_printf(const char *fmt, ...) attribute((format(printf,1,2)));
  * D(("the value of x is %d", x));
  * @endcode
  */
-#define D(x) do {                               \
-  if(sftp_debugging)                            \
-    sftp_debug_printf x;                        \
-} while(0)
+#  define D(x)                                                                 \
+    do {                                                                       \
+      if(sftp_debugging)                                                       \
+        sftp_debug_printf x;                                                   \
+    } while(0)
 
 #endif /* DEBUG_H */
 
diff --git a/dirname.c b/dirname.c
index 3c478f1..bf08459 100644
--- a/dirname.c
+++ b/dirname.c
@@ -34,7 +34,7 @@ const char *sftp_dirname(struct allocator *a, const char *path) {
 
       assert(len + 1 != 0);
       d = sftp_alloc(a, len + 1);
-      memcpy(d, path, len);
+      sftp_memcpy(d, path, len);
       return d;
     } else
       return "/";
diff --git a/format-gconv-report b/format-gconv-report
index 6b50e5d..019a63f 100755
--- a/format-gconv-report
+++ b/format-gconv-report
@@ -1,6 +1,6 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
 # This file is part of the Green End SFTP Server.
-# Copyright (C) 2007 Richard Kettlewell
+# Copyright (C) 2007, 2018 Richard Kettlewell
 #
 # 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
@@ -59,18 +59,13 @@ for line in sys.stdin:
       covered_lines += this_lines * this_pc / 100.0
     name = None
 
-def cmp(a,b):
-  if percent[a] < percent[b]: return -1 
-  elif percent[a] > percent[b]: return 1
-  else: return 0
-
-keys = percent.keys()
-keys.sort(cmp)
+keys = list(percent.keys())
+keys.sort(key=lambda a: percent[a])
 
 if len(keys):
   for k in keys:
-    print "%20s: %d%%" % (k, percent[k])
-  print "Total coverage: %d%%" % (100 * (covered_lines / total_lines))
+    print("%20s: %d%%" % (k, percent[k]))
+  print("Total coverage: %d%%" % (100 * (covered_lines / total_lines)))
 
 if htmldir is not None and len(keys):
   index = open(os.path.join(htmldir, "index.html"), "w")
diff --git a/getopt.c b/getopt.c
index 4744e43..97198ba 100644
--- a/getopt.c
+++ b/getopt.c
@@ -1,3 +1,4 @@
+// clang-format off
 /* Getopt for GNU.
    NOTE: getopt is now part of the C library, so if you don't know what
    "Keep this file name-space clean" means, talk to drepper@gnu.org
diff --git a/getopt.h b/getopt.h
index b0147e9..157b45d 100644
--- a/getopt.h
+++ b/getopt.h
@@ -1,3 +1,4 @@
+// clang-format off
 /* Declarations for getopt.
    Copyright (C) 1989,90,91,92,93,94,96,97,98 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
diff --git a/getopt1.c b/getopt1.c
index 3d264f2..987c804 100644
--- a/getopt1.c
+++ b/getopt1.c
@@ -1,3 +1,4 @@
+// clang-format off
 /* getopt_long and getopt_long_only entry points for GNU getopt.
    Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
      Free Software Foundation, Inc.
diff --git a/globals.c b/globals.c
index 592f47f..805ae31 100644
--- a/globals.c
+++ b/globals.c
@@ -21,11 +21,32 @@
 #include "sftpcommon.h"
 #include "types.h"
 #include "globals.h"
+#include "thread.h"
+#include "utils.h"
+#include <stdlib.h>
+#include <string.h>
 
 #if NTHREADS > 1
 struct queue *workqueue = 0;
 #endif
 
+static pthread_mutex_t state_lock = PTHREAD_MUTEX_INITIALIZER;
+static enum sftp_state state;
+
+void sftp_state_set(enum sftp_state s) {
+  ferrcheck(pthread_mutex_lock(&state_lock));
+  state = s;
+  ferrcheck(pthread_mutex_unlock(&state_lock));
+}
+
+enum sftp_state sftp_state_get(void) {
+  enum sftp_state r;
+  ferrcheck(pthread_mutex_lock(&state_lock));
+  r = state;
+  ferrcheck(pthread_mutex_unlock(&state_lock));
+  return r;
+}
+
 /*
 Local Variables:
 c-basic-offset:2
diff --git a/globals.h b/globals.h
index 1ae5f43..2e7382b 100644
--- a/globals.h
+++ b/globals.h
@@ -21,14 +21,14 @@
 /** @file globals.h @brief Global variables interface */
 
 #ifndef GLOBALS_H
-#define GLOBALS_H
+#  define GLOBALS_H
 
-#if NTHREADS > 1
+#  if NTHREADS > 1
 /** @brief Work queue for the thread pool */
 extern struct queue *workqueue;
-#else
-# define workqueue 0
-#endif
+#  else
+#    define workqueue 0
+#  endif
 
 /** @brief V6 protocol callbacks */
 extern const struct sftpprotocol sftp_v6;
diff --git a/handle.c b/handle.c
index eb7bf26..33cad28 100644
--- a/handle.c
+++ b/handle.c
@@ -34,14 +34,14 @@
 
 /** @brief Handle data structure */
 struct handle {
-  int type;                             /**< @brief @ref SSH_FXP_OPEN or @ref SSH_FXP_OPENDIR */
-  uint32_t tag;                         /**< @brief Unique tag or 0 for unused */
+  int type;     /**< @brief @ref SSH_FXP_OPEN or @ref SSH_FXP_OPENDIR */
+  uint32_t tag; /**< @brief Unique tag or 0 for unused */
   union {
-    int fd;                             /**< @brief File descriptor for a file */
-    DIR *dir;                           /**< @brief Directory stream */
+    int fd;   /**< @brief File descriptor for a file */
+    DIR *dir; /**< @brief Directory stream */
   } u;
-  char *path;                           /**< @brief Name of file or directory */
-  unsigned flags;                       /**< @brief Flags */
+  char *path;     /**< @brief Name of file or directory */
+  unsigned flags; /**< @brief Flags */
 };
 
 /** @brief Table of handles */
@@ -71,23 +71,23 @@ static void find_free_handle(struct handleid *id, int type) {
     /* need more space */
     nhandles = (nhandles ? 2 * nhandles : 16);
     assert(nhandles != 0);
-    handles = xrecalloc(handles, nhandles, sizeof (*handles));
-    memset(handles + n, 0, (nhandles - n) * sizeof (*handles));
+    handles = sftp_xrecalloc(handles, nhandles, sizeof(*handles));
+    sftp_memset(handles + n, 0, (nhandles - n) * sizeof(*handles));
   }
   while(!sequence)
-    ++sequence;                         /* never have a tag of 0 */
+    ++sequence; /* never have a tag of 0 */
   handles[n].tag = sequence++;
   handles[n].type = type;
   id->id = n;
   id->tag = handles[n].tag;
 }
 
-void sftp_handle_new_file(struct handleid *id, 
-                     int fd, const char *path, unsigned flags) {
+void sftp_handle_new_file(struct handleid *id, int fd, const char *path,
+                          unsigned flags) {
   ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
   find_free_handle(id, SSH_FXP_OPEN);
   handles[id->id].u.fd = fd;
-  handles[id->id].path = xstrdup(path);
+  handles[id->id].path = sftp_xstrdup(path);
   handles[id->id].flags = flags;
   ferrcheck(pthread_mutex_unlock(&sftp_handle_lock));
 }
@@ -96,18 +96,17 @@ void sftp_handle_new_dir(struct handleid *id, DIR *dp, const char *path) {
   ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
   find_free_handle(id, SSH_FXP_OPENDIR);
   handles[id->id].u.dir = dp;
-  handles[id->id].path = xstrdup(path);
+  handles[id->id].path = sftp_xstrdup(path);
   ferrcheck(pthread_mutex_unlock(&sftp_handle_lock));
 }
 
-uint32_t sftp_handle_get_fd(const struct handleid *id,
-                       int *fd, unsigned *flagsp) {
+uint32_t sftp_handle_get_fd(const struct handleid *id, int *fd,
+                            unsigned *flagsp) {
   uint32_t rc;
 
   ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
-  if(id->id < nhandles
-     && id->tag == handles[id->id].tag
-     && handles[id->id].type == SSH_FXP_OPEN) {
+  if(id->id < nhandles && id->tag == handles[id->id].tag &&
+     handles[id->id].type == SSH_FXP_OPEN) {
     *fd = handles[id->id].u.fd;
     if(flagsp)
       *flagsp = handles[id->id].flags;
@@ -118,14 +117,13 @@ uint32_t sftp_handle_get_fd(const struct handleid *id,
   return rc;
 }
 
-uint32_t sftp_handle_get_dir(const struct handleid *id,
-                        DIR **dp, const char **pathp) {
+uint32_t sftp_handle_get_dir(const struct handleid *id, DIR **dp,
+                             const char **pathp) {
   uint32_t rc;
 
   ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
-  if(id->id < nhandles
-     && id->tag == handles[id->id].tag
-     && handles[id->id].type == SSH_FXP_OPENDIR) {
+  if(id->id < nhandles && id->tag == handles[id->id].tag &&
+     handles[id->id].type == SSH_FXP_OPENDIR) {
     *dp = handles[id->id].u.dir;
     if(pathp)
       *pathp = handles[id->id].path;
@@ -142,9 +140,8 @@ uint32_t sftp_handle_close(const struct handleid *id) {
   if(!id->tag)
     return SSH_FX_INVALID_HANDLE;
   ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
-  if(id->id < nhandles
-     && id->tag == handles[id->id].tag) {
-    handles[id->id].tag = 0;            /* free up */
+  if(id->id < nhandles && id->tag == handles[id->id].tag) {
+    handles[id->id].tag = 0; /* free up */
     switch(handles[id->id].type) {
     case SSH_FXP_OPEN:
       if(close(handles[id->id].u.fd) < 0)
@@ -163,8 +160,7 @@ uint32_t sftp_handle_close(const struct handleid *id) {
     }
     free(handles[id->id].path);
     handles[id->id].path = NULL;
-  }
-  else
+  } else
     rc = SSH_FX_INVALID_HANDLE;
   ferrcheck(pthread_mutex_unlock(&sftp_handle_lock));
   return rc;
@@ -174,8 +170,7 @@ unsigned sftp_handle_flags(const struct handleid *id) {
   unsigned rc;
 
   ferrcheck(pthread_mutex_lock(&sftp_handle_lock));
-  if(id->id < nhandles
-     && id->tag == handles[id->id].tag)
+  if(id->id < nhandles && id->tag == handles[id->id].tag)
     rc = handles[id->id].flags;
   else
     rc = 0;
diff --git a/handle.h b/handle.h
index 2f65d02..fa5a27d 100644
--- a/handle.h
+++ b/handle.h
@@ -21,9 +21,9 @@
 /** @file handle.h @brief File handle interface */
 
 #ifndef HANDLE_H
-#define HANDLE_H
+#  define HANDLE_H
 
-#include <dirent.h>
+#  include <dirent.h>
 
 /** @brief Definition of a handle */
 struct handleid {
@@ -52,20 +52,20 @@ struct handleid {
  * - @ref HANDLE_TEXT
  * - @ref HANDLE_APPEND
  */
-void sftp_handle_new_file(struct handleid *id, int fd, const char *path, 
+void sftp_handle_new_file(struct handleid *id, int fd, const char *path,
                           unsigned flags);
 
 /** @brief Handle flag for text files
  *
  * See sftp_handle_new_file().
  */
-#define HANDLE_TEXT 0x0001
+#  define HANDLE_TEXT 0x0001
 
 /** @brief Handle flag for append-mode files
  *
  * See sftp_handle_new_file().
  */
-#define HANDLE_APPEND 0x0002
+#  define HANDLE_APPEND 0x0002
 
 /** @brief Create a new directory handle
  * @param id Where to store new handle
@@ -88,8 +88,7 @@ unsigned sftp_handle_flags(const struct handleid *id);
  * @param flagsp Where to store flags, or a null pointer
  * @return 0 on success, @ref SSH_FX_INVALID_HANDLE on error
  */
-uint32_t sftp_handle_get_fd(const struct handleid *id, 
-                            int *fd,
+uint32_t sftp_handle_get_fd(const struct handleid *id, int *fd,
                             unsigned *flagsp);
 
 /** @brief Retrieve the directory stream attached to handle @p id
@@ -102,8 +101,8 @@ uint32_t sftp_handle_get_fd(const struct handleid *id,
  * points to the handle's copy of the path name.  It will not outlive the
  * handle.
  */
-uint32_t sftp_handle_get_dir(const struct handleid *id,
-                             DIR **dp, const char **pathp);
+uint32_t sftp_handle_get_dir(const struct handleid *id, DIR **dp,
+                             const char **pathp);
 
 /** @brief Destroy a handle
  * @param id Handle to close
diff --git a/parse.c b/parse.c
index 92a6be0..10e45b9 100644
--- a/parse.c
+++ b/parse.c
@@ -27,6 +27,7 @@
 #include "sftp.h"
 #include "globals.h"
 #include "putword.h"
+#include "utils.h"
 #include <string.h>
 
 uint32_t sftp_parse_uint8(struct sftpjob *job, uint8_t *ur) {
@@ -71,14 +72,14 @@ uint32_t sftp_parse_string(struct sftpjob *job, char **strp, size_t *lenp) {
   if((rc = sftp_parse_uint32(job, &len)) != SSH_FX_OK)
     return rc;
   if(len == 0xFFFFFFFF)
-    return SSH_FX_BAD_MESSAGE;          /* overflow */
+    return SSH_FX_BAD_MESSAGE; /* overflow */
   if(job->left < len)
-    return SSH_FX_BAD_MESSAGE;          /* not enough bytes to satisfy */
+    return SSH_FX_BAD_MESSAGE; /* not enough bytes to satisfy */
   if(lenp)
     *lenp = len;
   if(strp) {
-    str = sftp_alloc(job->a, len + 1);  /* 0-fills */
-    memcpy(str, job->ptr, len);
+    str = sftp_alloc(job->a, len + 1); /* 0-fills */
+    sftp_memcpy(str, job->ptr, len);
     *strp = str;
   }
   job->ptr += len;
@@ -88,7 +89,7 @@ uint32_t sftp_parse_string(struct sftpjob *job, char **strp, size_t *lenp) {
 
 uint32_t sftp_parse_path(struct sftpjob *job, char **strp) {
   uint32_t rc;
-  
+
   if((rc = sftp_parse_string(job, strp, 0)) != SSH_FX_OK)
     return rc;
   return protocol->decode(job, strp);
@@ -97,10 +98,12 @@ uint32_t sftp_parse_path(struct sftpjob *job, char **strp) {
 uint32_t sftp_parse_handle(struct sftpjob *job, struct handleid *id) {
   uint32_t len, rc;
 
-  if((rc = sftp_parse_uint32(job, &len)) != SSH_FX_OK
-     || len != 8
-     || (rc = sftp_parse_uint32(job, &id->id)) != SSH_FX_OK
-     || (rc = sftp_parse_uint32(job, &id->tag) != SSH_FX_OK))
+  if((rc = sftp_parse_uint32(job, &len)) != SSH_FX_OK)
+    return rc;
+  if(len != 8)
+    return SSH_FX_BAD_MESSAGE;
+  if((rc = sftp_parse_uint32(job, &id->id)) != SSH_FX_OK ||
+     (rc = sftp_parse_uint32(job, &id->tag) != SSH_FX_OK))
     return rc;
   return SSH_FX_OK;
 }
diff --git a/parse.h b/parse.h
index 6ef3a64..6a27a08 100644
--- a/parse.h
+++ b/parse.h
@@ -21,7 +21,7 @@
 /** @file parse.h @brief Message parsing interface */
 
 #ifndef PARSE_H
-#define PARSE_H
+#  define PARSE_H
 
 /** @brief Retrieve the next byte from a message
  * @param job Job containing message
@@ -84,34 +84,36 @@ uint32_t sftp_parse_path(struct sftpjob *job, char **strp);
  */
 uint32_t sftp_parse_handle(struct sftpjob *job, struct handleid *id);
 
-#if CLIENT
+#  if CLIENT
 /** @brief Error checking wrapper for sftp_parse_... functions
  * @param E expression to check
  *
- * If the parse fails, @ref fatal() is called.  This macro is only used in the
- * client.
+ * If the parse fails, @ref sftp_fatal() is called.  This macro is only used in
+ * the client.
  */
-#define cpcheck(E) do {                                                 \
-  const uint32_t rc = (E);                                              \
-  if(rc) {                                                              \
-    D(("%s:%d: %s returned %"PRIu32, __FILE__, __LINE__, #E, rc));      \
-    fatal("error parsing response from server");                        \
-  }                                                                     \
-} while(0)
-#else
+#    define cpcheck(E)                                                         \
+      do {                                                                     \
+        const uint32_t rc = (E);                                               \
+        if(rc) {                                                               \
+          D(("%s:%d: %s returned %" PRIu32, __FILE__, __LINE__, #E, rc));      \
+          sftp_fatal("error parsing response from server");                    \
+        }                                                                      \
+      } while(0)
+#  else
 /** @brief Error checking wrapper for sftp_parse_... functions
  * @param E expression to check
  *
  * If the parse fails, @c return is invoked with the error code.
  */
-#define pcheck(E) do {                                          \
-  const uint32_t rc = (E);                                      \
-  if(rc != SSH_FX_OK) {                                         \
-    D(("%s:%d: %s: %"PRIu32, __FILE__, __LINE__, #E, rc));      \
-    return rc;                                                  \
-  }                                                             \
-} while(0)
-#endif
+#    define pcheck(E)                                                          \
+      do {                                                                     \
+        const uint32_t rc = (E);                                               \
+        if(rc != SSH_FX_OK) {                                                  \
+          D(("%s:%d: %s: %" PRIu32, __FILE__, __LINE__, #E, rc));              \
+          return rc;                                                           \
+        }                                                                      \
+      } while(0)
+#  endif
 
 #endif /* PARSE_H */
 
diff --git a/putword.h b/putword.h
index 9e185ad..9657654 100644
--- a/putword.h
+++ b/putword.h
@@ -21,28 +21,29 @@
 /** @file putword.h @brief Macros for storing network-order values */
 
 #ifndef PUTWORD_H
-#define PUTWORD_H
+#  define PUTWORD_H
 
-#include <arpa/inet.h>
+#  include <arpa/inet.h>
 
-#ifndef ASM
-# define ASM 1
-#endif
+#  ifndef ASM
+#    define ASM 1
+#  endif
 
 /** @brief Unaligned 16-bit network-order store
  * @param where Where to store value
  * @param u Value to store
  */
 static inline void put16(void *where, uint16_t u) {
-#if (__i386__ || __amd64__) && __GNUC__ && ASM
+#  if(__i386__ || __amd64__) && __GNUC__ && ASM
   __asm__ volatile("xchg %h[U],%b[U]\n\tmovw %[U],%[WHERE]"
-                   : [U] "+Q" (u)
-                   : [WHERE] "m" (*(uint16_t *)where));
-#else
+                   : [U] "+Q"(u)
+                   : [WHERE] "m"(*(uint16_t *)where)
+                   : "memory");
+#  else
   uint8_t *ptr = where;
   *ptr++ = (uint8_t)(u >> 8);
   *ptr = (uint8_t)u;
-#endif
+#  endif
 }
 
 /** @brief Unaligned 32-bit network-order store
@@ -50,17 +51,18 @@ static inline void put16(void *where, uint16_t u) {
  * @param u Value to store
  */
 static inline void put32(void *where, uint32_t u) {
-#if (__i386__ || __amd64__) && __GNUC__ && ASM
+#  if(__i386__ || __amd64__) && __GNUC__ && ASM
   __asm__ volatile("bswapl %[U]\n\tmovl %[U],%[WHERE]"
-                   : [U] "+r" (u)
-                   : [WHERE] "m" (*(uint32_t *)where));
-#else
+                   : [U] "+r"(u)
+                   : [WHERE] "m"(*(uint32_t *)where)
+                   : "memory");
+#  else
   uint8_t *ptr = where;
   *ptr++ = (uint8_t)(u >> 24);
   *ptr++ = (uint8_t)(u >> 16);
   *ptr++ = (uint8_t)(u >> 8);
   *ptr++ = (uint8_t)(u);
-#endif
+#  endif
 }
 
 /** @brief Unaligned 64-bit network-order store
@@ -68,14 +70,15 @@ static inline void put32(void *where, uint32_t u) {
  * @param u Value to store
  */
 static inline void put64(void *where, uint64_t u) {
-#if __amd64__ && __GNUC__ && ASM
+#  if __amd64__ && __GNUC__ && ASM
   __asm__ volatile("bswapq %[U]\n\tmovq %[U],%[WHERE]"
-                   : [U] "+r" (u)
-                   : [WHERE] "m" (*(uint64_t *)where));
-#else
+                   : [U] "+r"(u)
+                   : [WHERE] "m"(*(uint64_t *)where)
+                   : "memory");
+#  else
   put32(where, u >> 32);
   put32((char *)where + 4, (uint32_t)u);
-#endif
+#  endif
 }
 
 /** @brief Unaligned 16-bit network-order fetch
@@ -83,16 +86,16 @@ static inline void put64(void *where, uint64_t u) {
  * @return Fetched value
  */
 static inline uint16_t get16(const void *where) {
-#if (__i386__ || __amd64__) && __GNUC__ && ASM
+#  if(__i386__ || __amd64__) && __GNUC__ && ASM
   uint16_t r;
   __asm__("movw %[WHERE],%[R]\t\nxchg %h[R],%b[R]"
-          : [R] "=Q" (r)
-          : [WHERE] "m" (*(const uint16_t *)where));
+          : [R] "=Q"(r)
+          : [WHERE] "m"(*(const uint16_t *)where));
   return r;
-#else
+#  else
   const uint8_t *ptr = where;
   return (ptr[0] << 8) + ptr[1];
-#endif
+#  endif
 }
 
 /** @brief Unaligned 32-bit network-order fetch
@@ -100,16 +103,16 @@ static inline uint16_t get16(const void *where) {
  * @return Fetched value
  */
 static inline uint32_t get32(const void *where) {
-#if (__i386__ || __amd64__) && __GNUC__ && ASM
+#  if(__i386__ || __amd64__) && __GNUC__ && ASM
   uint32_t r;
   __asm__("movl %[WHERE],%[R]\n\tbswapl %[R]"
-          : [R] "=r" (r)
-          : [WHERE] "m" (*(const uint32_t *)where));
+          : [R] "=r"(r)
+          : [WHERE] "m"(*(const uint32_t *)where));
   return r;
-#else
+#  else
   const uint8_t *ptr = where;
   return ((unsigned)ptr[0] << 24) + (ptr[1] << 16) + (ptr[2] << 8) + ptr[3];
-#endif
+#  endif
 }
 
 /** @brief Unaligned 64-bit network-order fetch
@@ -117,15 +120,15 @@ static inline uint32_t get32(const void *where) {
  * @return Fetched value
  */
 static inline uint64_t get64(const void *where) {
-#if __amd64__ && __GNUC__ && ASM
+#  if __amd64__ && __GNUC__ && ASM
   uint64_t r;
   __asm__("movq %[WHERE],%[R]\n\tbswapq %[R]"
-          : [R] "=r" (r)
-          : [WHERE] "m" (*(const uint64_t *)where));
+          : [R] "=r"(r)
+          : [WHERE] "m"(*(const uint64_t *)where));
   return r;
-#else
+#  else
   return ((uint64_t)get32(where) << 32) + get32((const char *)where + 4);
-#endif
+#  endif
 }
 
 #endif /* PUTWORD_H */
diff --git a/pwtest.c b/pwtest.c
index 1910462..7adb290 100644
--- a/pwtest.c
+++ b/pwtest.c
@@ -19,6 +19,7 @@
  */
 #include "sftpcommon.h"
 #include "putword.h"
+#include "utils.h"
 #include <string.h>
 #include <assert.h>
 
@@ -27,7 +28,7 @@ int main() {
   int n, m;
 
   for(n = 0; n <= 14; ++n) {
-    memset(buffer, 0xAF, 16);
+    sftp_memset(buffer, 0xAF, 16);
     put16(buffer + n, 0x0102);
     assert(get16(buffer + n) == 0x0102);
     for(m = 0; m < 16; ++m) {
@@ -39,9 +40,9 @@ int main() {
   }
 
   for(n = 0; n <= 12; ++n) {
-    memset(buffer, 0xAF, 16);
+    sftp_memset(buffer, 0xAF, 16);
     put32(buffer + n, 0x01020304);
-    //assert(get32(buffer + n) == 0x01020304);
+    // assert(get32(buffer + n) == 0x01020304);
     for(m = 0; m < 16; ++m) {
       if(m >= n && m < n + 4)
         assert(buffer[m] == 1 + m - n);
@@ -51,9 +52,9 @@ int main() {
   }
 
   for(n = 0; n <= 8; ++n) {
-    memset(buffer, 0xAF, 16);
+    sftp_memset(buffer, 0xAF, 16);
     put64(buffer + n, 0x0102030405060708ULL);
-    //assert(get64(buffer + n) == 0x0102030405060708ULL);
+    // assert(get64(buffer + n) == 0x0102030405060708ULL);
     for(m = 0; m < 16; ++m) {
       if(m >= n && m < n + 8)
         assert(buffer[m] == 1 + m - n);
diff --git a/queue.c b/queue.c
index 81c3327..bd87bad 100644
--- a/queue.c
+++ b/queue.c
@@ -103,21 +103,20 @@ static void *queue_thread(void *vq) {
   return 0;
 }
 
-void queue_init(struct queue **qr,
-		const struct queuedetails *details,
-		int nthreads) {
+void queue_init(struct queue **qr, const struct queuedetails *details,
+                int nthreads) {
   int n;
   struct queue *q;
 
-  q = xmalloc(sizeof *q);
-  memset(q, 0, sizeof *q);
+  q = sftp_xmalloc(sizeof *q);
+  sftp_memset(q, 0, sizeof *q);
   q->jobs = 0;
   q->jobstail = &q->jobs;
   ferrcheck(pthread_mutex_init(&q->m, 0));
   ferrcheck(pthread_cond_init(&q->c, 0));
   q->details = details;
   q->nthreads = nthreads;
-  q->threads = xcalloc(nthreads, sizeof (pthread_t));
+  q->threads = sftp_xcalloc(nthreads, sizeof(pthread_t));
   q->join = 0;
   for(n = 0; n < q->nthreads; ++n)
     ferrcheck(pthread_create(&q->threads[n], 0, queue_thread, q));
@@ -127,7 +126,7 @@ void queue_init(struct queue **qr,
 void queue_add(struct queue *q, void *job) {
   struct queuejob *qj;
 
-  qj = xmalloc(sizeof *qj);
+  qj = sftp_xmalloc(sizeof *qj);
   qj->next = 0;
   qj->job = job;
   ferrcheck(pthread_mutex_lock(&q->m));
@@ -139,7 +138,7 @@ void queue_add(struct queue *q, void *job) {
 
 void queue_destroy(struct queue *q) {
   int n;
-  
+
   if(q) {
     ferrcheck(pthread_mutex_lock(&q->m));
     q->join = 1;
diff --git a/queue.h b/queue.h
index 552d533..cbebc23 100644
--- a/queue.h
+++ b/queue.h
@@ -21,18 +21,18 @@
 /** @file queue.h @brief Thread pool/queue interface */
 
 #ifndef QUEUE_H
-#define QUEUE_H
+#  define QUEUE_H
 
 struct allocator;
 
-#if NTHREADS > 1
+#  if NTHREADS > 1
 
 /** @brief Queue-specific callbacks */
 struct queuedetails {
   /** @brief Per-thread initialization
    * @return Per-thread value to be passed to other callbacks
    */
-  void *(*init)();
+  void *(*init)(void);
 
   /** @brief Worker method
    * @param job Job to process
@@ -52,9 +52,8 @@ struct queuedetails {
  * @param details Queue-specific callbacks (not copied)
  * @param nthreads Number of threads to create
  */
-void queue_init(struct queue **qp,
-		const struct queuedetails *details,
-		int nthreads);
+void queue_init(struct queue **qp, const struct queuedetails *details,
+                int nthreads);
 
 /** @brief Add a job to a thread pool's queue
  * @param q Queue pointer
@@ -71,7 +70,7 @@ void queue_add(struct queue *q, void *job);
  * All unprocessed jobs are executed before completion. */
 void queue_destroy(struct queue *q);
 
-#endif
+#  endif
 
 #endif /* QUEUE_H */
 
diff --git a/readwrite.c b/readwrite.c
index aabe878..7a1af21 100644
--- a/readwrite.c
+++ b/readwrite.c
@@ -19,4 +19,3 @@
  */
 
 int readonly;
-
diff --git a/realpath.c b/realpath.c
index 5702883..56e0a88 100644
--- a/realpath.c
+++ b/realpath.c
@@ -32,9 +32,10 @@
 #include <limits.h>
 
 static char *process_path(struct allocator *a, char *result, size_t *nresultp,
-			  const char *path, unsigned flags);
+                          const char *path, unsigned flags);
 
-char *sftp_find_realpath(struct allocator *a, const char *path, unsigned flags) {
+char *sftp_find_realpath(struct allocator *a, const char *path,
+                         unsigned flags) {
   char *cwd, *abspath, *result = 0;
   size_t nresult = 0;
 
@@ -58,7 +59,7 @@ char *sftp_find_realpath(struct allocator *a, const char *path, unsigned flags)
   }
 
   /* The result always starts with a / */
-  result = append(a, result, &nresult, "/");
+  result = sftp_str_append(a, result, &nresult, "/");
 
   /* All the work happens below */
   return process_path(a, result, &nresult, path, flags);
@@ -73,7 +74,7 @@ char *sftp_find_realpath(struct allocator *a, const char *path, unsigned flags)
  * @return Modified result
  */
 static char *process_path(struct allocator *a, char *result, size_t *nresultp,
-			  const char *path, unsigned flags) {
+                          const char *path, unsigned flags) {
   D(("process_path path='%s' result='%s'", path, result));
   while(*path) {
     if(*path == '/')
@@ -92,20 +93,20 @@ static char *process_path(struct allocator *a, char *result, size_t *nresultp,
         if(ls != result)
           *ls = 0;
         else
-          strcpy(result, "/");          /* /.. = / */
+          strcpy(result, "/"); /* /.. = / */
         D(("result[0] -> '%s'", result));
       } else {
         const size_t oldresultlen = strlen(result);
         /* Append the new path element */
         if(result[1])
-          result = append(a, result, nresultp, "/");
-        result = appendn(a, result, nresultp, path, elementlen);
+          result = sftp_str_append(a, result, nresultp, "/");
+        result = sftp_str_appendn(a, result, nresultp, path, elementlen);
         D(("result[1] -> '%s'", result));
         /* If we're following symlinks, see if the path so far points to a
          * link */
         if(flags & RP_READLINK) {
           const char *const target = sftp_do_readlink(a, result);
-        
+
           if(target) {
             if(target[0] == '/')
               /* Absolute symlink, go back to the root */
@@ -134,7 +135,7 @@ static char *process_path(struct allocator *a, char *result, size_t *nresultp,
         }
         D(("result[2] -> '%s'", result));
       }
-     path += elementlen;
+      path += elementlen;
     }
   }
   D(("returning '%s'", result));
diff --git a/run-tests b/run-tests
index c43fe40..cf89d0d 100755
--- a/run-tests
+++ b/run-tests
@@ -1,7 +1,7 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
 #
 # This file is part of the Green End SFTP Server.
-# Copyright (C) 2007, 2011, 2016 Richard Kettlewell
+# Copyright (C) 2007, 2011, 2016, 2018 Richard Kettlewell
 #
 # 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
@@ -18,32 +18,38 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 # USA
 
-import os,sys,re,string
-from subprocess import Popen,PIPE,STDOUT
+import os
+import sys
+import re
+import string
+from subprocess import Popen, PIPE, STDOUT
 
 srcdir = os.path.abspath(os.getenv('srcdir'))
 builddir = os.path.abspath('.')
 client = os.path.abspath("sftpclient")
 server = "gesftpserver"
 
+
 def rmrf(path):
     if os.path.lexists(path):
         if (not os.path.islink(path)) and os.path.isdir(path):
-            os.chmod(path, 0700)
+            os.chmod(path, 0o700)
             for name in os.listdir(path):
-                rmrf(os.path.join(path,name))
+                rmrf(os.path.join(path, name))
             os.rmdir(path)
         else:
             os.remove(path)
 
+
 def fatal(msg):
     sys.stderr.write("%s\n" % msg)
     sys.exit(1)
 
+
 if os.getuid() == 0:
     fatal("These tests are not suitable for running as root.")
 
-os.umask(022)                           # for consistent permissions
+os.umask(0o22)                           # for consistent permissions
 failed = 0
 protocols = ['2', '3', '4', '5', '6', '7']
 dir = 'tests'
@@ -56,7 +62,7 @@ while len(args) > 0 and args[0][0] == '-':
         args = args[2:]
     elif args[0] == "--server":
         server = args[1]
-        args = args[2:] 
+        args = args[2:]
     elif args[0] == "--directory":
         dir = args[1]
         args = args[2:]
@@ -72,85 +78,127 @@ if len(args) > 0:
     tests = args
 else:
     tests = os.listdir(os.path.join(srcdir, dir))
+# Execute tests in a consistent order
 tests.sort()
 
 # Clean up
 rmrf(os.path.join(builddir, ',testroot'))
 
+# Colorize output (if possible)
+
+
+def colored(text, color=None, on_color=None, attrs=None):
+    """Uncolorized output"""
+    return text
+
+
+if sys.stdout.isatty():
+    try:
+        import termcolor
+        colored = termcolor.colored
+    except:
+        pass
+
 for test in tests:
     for proto in protocols:
+        # Skip dotfiles, backup files, and tests that don't apply to the
+        # current protocol
         if ('.' in test
             or not proto in test
             or '#' in test
-            or '~' in test):
+                or '~' in test):
             continue
         sys.stderr.write("Testing %s/%s protocol %s ... " % (dir, test, proto))
-        root = os.path.join(builddir, ',testroot','%s.%s' % (test, proto))
+        # Make a working directory for the test
+        root = os.path.join(builddir, ',testroot', '%s.%s' % (test, proto))
         os.makedirs(root)
         os.chdir(root)
-        clientcmd=[client,
-                   "--force-version", proto,
-                   "-P", server,
-                   "-b", os.path.join(srcdir, dir, test),
-                   '--echo',
-                   '--fix-sigpipe',   # stupid Python
-                   '--no-stop-on-error']
+        # Run the client with the server as a child process
+        clientcmd = [client,
+                     "--force-version", proto,
+                     "-P", server,
+                     "-b", os.path.join(srcdir, dir, test),
+                     '--echo',
+                     '--fix-sigpipe',   # stupid Python
+                     '--no-stop-on-error']
         if debug:
-            clientcmd+=["--program-debug-path",
-                        "%s/%s-%s.debug" % (builddir, test, proto)]
+            debug_path = "%s/%s-%s.debug" % (builddir, test, proto)
+            # Save server debug output
+            clientcmd += ["--program-debug-path", debug_path]
+        # Run the client
         output = Popen(clientcmd,
                        stdout=PIPE,
-                       stderr=STDOUT).communicate()[0].split('\n')
+                       stderr=STDOUT).communicate()[0].split(b'\n')
+        # Get the output, with newlines stripped
+        output = [str(s, "ASCII") for s in output]
         if output[len(output)-1] == "":
             output = output[:-1]
-        n = 0
-        errors = []
-        for expected in file(os.path.join(srcdir, dir, '%s' % test)):
-            expected = expected[:-1]    # strip newline
-            if n >= len(output):
-                errors.append("EXPECTED[%d]: %s" % (n, expected))
-                errors.append("     GOT[%d]: EOF" % n)
-                break
-            got = output[n]
-            n += 1
-            if len(expected) > 0 and expected[0] == '#':
-                expected = expected[1:]
-                try:
-                    if not re.match(expected, got):
-                        errors.append("EXPECTED[%d]: %s" % (n + 1, expected))
-                        errors.append("     GOT[%d]: %s" % (n + 1, got))
-                except:
-                    print "\n\nPossible invalid regexp:\n%s\n" % expected
-                    raise
+        # Get the script, with newlines stripped
+        with open(os.path.join(srcdir, dir, '%s' % test), "r") as f:
+            script = [l[:-1] for l in f]
+        # Find the maximum line length in each
+        omax = max([len(l) for l in output])
+        smax = max([len(l) for l in script])
+        errors = 0
+        report = []
+        # Iterate over the lines, checking them and formatting the results
+        for lineno in range(0, max(len(output), len(script))):
+            if lineno >= len(output):
+                # Truncated output is bad
+                ok = False
+                sline = script[lineno]
+                oline = ""
+            elif lineno >= len(script):
+                # Excessive output is bad
+                ok = False
+                sline = ""
+                oline = output[lineno]
+            else:
+                sline = script[lineno]
+                oline = output[lineno]
+                if len(sline) > 0 and sline[0] == '#':
+                    # Lines starting # are regexps matching expected output
+                    pattern = sline[1:]
+                    ok = re.match(pattern, oline)
+                else:
+                    # Other lines are the commands, which we expect to be
+                    # echoed back.
+                    ok = (oline == sline)
+            if ok:
+                marker = " "
+                def f(t): return t
             else:
-                if expected != got:
-                    errors.append("EXPECTED[%d]: %s" % (n + 1, expected))
-                    errors.append("     GOT[%d]: %s" % (n + 1, got))
-        if n < len(output):
-            while n < len(output):
-                errors.append("   EXTRA[%d]: %s" % (n + 1, output[n]))
-                n += 1
-        if len(errors) > 0:
-            sys.stderr.write("FAILED\n")
-            sys.stderr.write("---errors---\n");
-            for n in range(0, len(errors)):
-                sys.stderr.write("%3d: %s\n" % (n+1, errors[n]))
-            sys.stderr.write("\n")
-            sys.stderr.write("---output---\n");
-            for n in range(0, len(output)):
-                sys.stderr.write("%3d: %s\n" % (n+1, output[n]))
-            sys.stderr.write("---end---\n");
+                # Mismatching lines are marked with a * and colored red (if
+                # possible)
+                marker = "*"
+                errors += 1
+                def f(t): return colored(t, "red")
+            report.append(f("%s %-*s %-*s\n" %
+                          (marker, smax, sline, omax, oline)))
+        if errors > 0:
+            sys.stderr.write(colored("FAILED\n", "red"))
+            sys.stderr.write("Command:\n  %s\n" % " ".join(clientcmd))
+            sys.stderr.write("Output discrepancies:\n")
+            for l in report:
+                sys.stderr.write(l)
+            if debug:
+                sys.stderr.write("Server debug:\n")
+                with open(debug_path, "r") as f:
+                    for l in f.readlines():
+                        sys.stderr.write(l)
             failed += 1
         else:
-            sys.stderr.write("passed\n")
+            sys.stderr.write(colored("passed\n", "green"))
 
 if failed:
-    print "%d tests failed" % failed
+    print(colored("%d tests failed" % failed, "red"))
     sys.exit(1)
 else:
+    # On success, delete the test root. It's preserved for inspection on
+    # failure.
     os.chdir("/")
     rmrf(os.path.join(builddir, ',testroot'))
-    print "OK"
+    print(colored("OK", "green"))
 
 # Local Variables:
 # mode:python
diff --git a/send.c b/send.c
index 57df723..42669cb 100644
--- a/send.c
+++ b/send.c
@@ -41,25 +41,28 @@
 static pthread_mutex_t output_lock = PTHREAD_MUTEX_INITIALIZER;
 #endif
 
-int sftpout = 1;                        /* default is stdout */
+int sftpout = 1; /* default is stdout */
 
 /** @brief Store a 16-bit value */
-#define sftp_send_raw16(u) do {                 \
-  put16(&w->buffer[w->bufused], u);             \
-  w->bufused += 2;                              \
-} while(0)
+#define sftp_send_raw16(u)                                                     \
+  do {                                                                         \
+    put16(&w->buffer[w->bufused], u);                                          \
+    w->bufused += 2;                                                           \
+  } while(0)
 
 /** @brief Store a 32-bit value */
-#define sftp_send_raw32(u) do {                 \
-  put32(&w->buffer[w->bufused], u);             \
-  w->bufused += 4;                              \
-} while(0)
+#define sftp_send_raw32(u)                                                     \
+  do {                                                                         \
+    put32(&w->buffer[w->bufused], u);                                          \
+    w->bufused += 4;                                                           \
+  } while(0)
 
 /** @brief Store a 64-bit value */
-#define sftp_send_raw64(u) do {                 \
-  put64(&w->buffer[w->bufused], u);             \
-  w->bufused += 8;                              \
-} while(0)
+#define sftp_send_raw64(u)                                                     \
+  do {                                                                         \
+    put64(&w->buffer[w->bufused], u);                                          \
+    w->bufused += 8;                                                           \
+  } while(0)
 
 void sftp_send_need(struct worker *w, size_t n) {
   assert(w->bufused < 0x80000000);
@@ -68,14 +71,14 @@ void sftp_send_need(struct worker *w, size_t n) {
     while(newsize && newsize < w->bufsize + n)
       newsize <<= 1;
     if(!newsize)
-      fatal("sftp_send_need: out of memory (%zu)", n);
-    w->buffer = xrealloc(w->buffer, w->bufsize = newsize);
+      sftp_fatal("sftp_send_need: out of memory (%zu)", n);
+    w->buffer = sftp_xrealloc(w->buffer, w->bufsize = newsize);
   }
 }
 
 void sftp_send_begin(struct worker *w) {
   w->bufused = 0;
-  sftp_send_uint32(w, 0);                    /* placeholder for length */
+  sftp_send_uint32(w, 0); /* placeholder for length */
 }
 
 void sftp_send_end(struct worker *w) {
@@ -98,7 +101,7 @@ void sftp_send_end(struct worker *w) {
     if((n = write(sftpout, w->buffer + written, w->bufused - written)) > 0)
       written += n;
     else if(n < 0)
-      fatal("error sending response: %s", strerror(errno));
+      sftp_fatal("error sending response: %s", strerror(errno));
   ferrcheck(pthread_mutex_unlock(&output_lock));
   w->bufused = 0x80000000;
 }
@@ -126,7 +129,7 @@ void sftp_send_uint64(struct worker *w, uint64_t u) {
 void sftp_send_bytes(struct worker *w, const void *bytes, size_t n) {
   sftp_send_need(w, n + 4);
   sftp_send_raw32(n);
-  memcpy(w->buffer + w->bufused, bytes, n);
+  sftp_memcpy(w->buffer + w->bufused, bytes, n);
   w->bufused += n;
 }
 
@@ -136,7 +139,7 @@ void sftp_send_string(struct worker *w, const char *s) {
 
 void sftp_send_path(struct sftpjob *job, struct worker *w, const char *path) {
   if(protocol->encode(job, (char **)&path))
-    fatal("cannot encode local path name '%s'", path);
+    sftp_fatal("cannot encode local path name '%s'", path);
   sftp_send_string(w, path);
 }
 
diff --git a/send.h b/send.h
index 93e06b6..351f227 100644
--- a/send.h
+++ b/send.h
@@ -21,7 +21,7 @@
 /** @file send.h @brief Message sending interface */
 
 #ifndef SEND_H
-#define SEND_H
+#  define SEND_H
 
 /** @brief Ensure there are @p n bytes spare in the message buffer
  * @param w Worker containing message
diff --git a/serialize.c b/serialize.c
index c3acdbc..9ce8837 100644
--- a/serialize.c
+++ b/serialize.c
@@ -53,10 +53,10 @@
  * to be clever and allow re-ordering of operations where different orders
  * couldn't make a difference.
  *
- * 4) Reads don't include @ref SSH_FXP_READDIR.  Therefore such requests are always
- * serialized, which saves us having to worry about the thread safety of the
- * <dirent.h> functions.  Indeed you could say this about any other operation
- * but readdir() is the most obvious one to worry about.
+ * 4) Reads don't include @ref SSH_FXP_READDIR.  Therefore such requests are
+ * always serialized, which saves us having to worry about the thread safety of
+ * the <dirent.h> functions.  Indeed you could say this about any other
+ * operation but readdir() is the most obvious one to worry about.
  *
  */
 
@@ -110,12 +110,11 @@ static inline int handles_equal(const struct handleid *h1,
  * @param b Serialization queue entry
  * @return Nonzero if the IO ranges for @p a and @p b overlap
  */
-static int ranges_overlap(const struct sqnode *a, 
-                          const struct sqnode *b) {
+static int ranges_overlap(const struct sqnode *a, const struct sqnode *b) {
   if(a->len && b->len) {
     const uint64_t aend = a->offset + a->len - 1;
     const uint64_t bend = b->offset + b->len - 1;
-    
+
     if(aend >= b->offset && aend <= bend)
       return 1;
     if(bend >= a->offset && bend <= aend)
@@ -135,8 +134,8 @@ static int ranges_overlap(const struct sqnode *a,
  */
 static int reorderable(const struct sqnode *q1, const struct sqnode *q2,
                        unsigned flags) {
-  if((q1->type == SSH_FXP_READ || q1->type == SSH_FXP_WRITE)
-     && (q2->type == SSH_FXP_READ || q2->type == SSH_FXP_WRITE)) {
+  if((q1->type == SSH_FXP_READ || q1->type == SSH_FXP_WRITE) &&
+     (q2->type == SSH_FXP_READ || q2->type == SSH_FXP_WRITE)) {
     /* We allow reads and writes to be re-ordered up to a point */
     if(!handles_equal(&q1->hid, &q2->hid)) {
       /* Operations on different handles can always be re-ordered. */
@@ -148,7 +147,7 @@ static int reorderable(const struct sqnode *q1, const struct sqnode *q2,
      * measure). */
     if(q1->type == SSH_FXP_READ && q2->type == SSH_FXP_READ)
       return 0;
-    if(flags & (HANDLE_TEXT|HANDLE_APPEND))
+    if(flags & (HANDLE_TEXT | HANDLE_APPEND))
       /* Operations on text or append-write files cannot be re-oredered. */
       return 0;
     if(q1->type == SSH_FXP_WRITE || q2->type == SSH_FXP_WRITE)
@@ -173,24 +172,26 @@ void queue_serializable_job(struct sftpjob *job) {
 
   job->ptr = job->data;
   job->left = job->len;
-  if(!sftp_parse_uint8(job, &type)
-     && (type == SSH_FXP_READ || type == SSH_FXP_WRITE)
-     && sftp_parse_uint32(job, &id) == SSH_FX_OK
-     && sftp_parse_handle(job, &hid) == SSH_FX_OK
-     && sftp_parse_uint64(job, &offset) == SSH_FX_OK
-     && sftp_parse_uint32(job, &len) == SSH_FX_OK) {
+  type = 0; // First sftp_parse_uint8 can't fail, but GCC LTO doesn't know this
+            // and moans
+  if(!sftp_parse_uint8(job, &type) &&
+     (type == SSH_FXP_READ || type == SSH_FXP_WRITE) &&
+     sftp_parse_uint32(job, &id) == SSH_FX_OK &&
+     sftp_parse_handle(job, &hid) == SSH_FX_OK &&
+     sftp_parse_uint64(job, &offset) == SSH_FX_OK &&
+     sftp_parse_uint32(job, &len) == SSH_FX_OK) {
     /* This is a well-formed read or write operation */
     len64 = len;
     handleflags = sftp_handle_flags(&hid);
   } else {
     /* Anything else has dummy values */
-    memset(&hid, 0, sizeof hid);
+    sftp_memset(&hid, 0, sizeof hid);
     offset = 0;
     len64 = ~(uint64_t)0;
     handleflags = 0;
   }
   ferrcheck(pthread_mutex_lock(&sq_mutex));
-  q = xmalloc(sizeof *q);
+  q = sftp_xmalloc(sizeof *q);
   q->older = newest;
   q->job = job;
   q->type = type;
diff --git a/serialize.h b/serialize.h
index a3b1815..559916e 100644
--- a/serialize.h
+++ b/serialize.h
@@ -21,7 +21,7 @@
 /** @file serialize.h @brief Request serialization interface */
 
 #ifndef SERIALIZE_H
-#define SERIALIZE_H
+#  define SERIALIZE_H
 
 /** @brief Establish a job's place in the serialization queue
  * @param job Job to establish
diff --git a/sftp.h b/sftp.h
index 9a576b7..c6bbc52 100644
--- a/sftp.h
+++ b/sftp.h
@@ -21,10 +21,14 @@
 /** @file sftp.h @brief SFTP definitions
  *
  * Specifications:
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-02.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-04.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-13.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-02.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-04.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-13.txt
  *
  * See also:
  * - @ref type
@@ -40,183 +44,183 @@
  */
 
 #ifndef SFTP_H
-#define SFTP_H
+#  define SFTP_H
 
 /** @defgroup type SFTP 'type' definitions
  * @{
  */
 
 /** @brief Protocol initialization */
-#define SSH_FXP_INIT                1
+#  define SSH_FXP_INIT 1
 
 /** @brief Server version */
-#define SSH_FXP_VERSION             2
+#  define SSH_FXP_VERSION 2
 
 /** @brief Open file */
-#define SSH_FXP_OPEN                3
+#  define SSH_FXP_OPEN 3
 
 /** @brief Close handle */
-#define SSH_FXP_CLOSE               4
+#  define SSH_FXP_CLOSE 4
 
 /** @brief Read bytes */
-#define SSH_FXP_READ                5
+#  define SSH_FXP_READ 5
 
 /** @brief Write bytes */
-#define SSH_FXP_WRITE               6
+#  define SSH_FXP_WRITE 6
 
 /** @brief Get file attributes by name
  *
  * Do not follow symlinks.
  */
-#define SSH_FXP_LSTAT               7
+#  define SSH_FXP_LSTAT 7
 
 /** @brief Get file attributes by handle */
-#define SSH_FXP_FSTAT               8
+#  define SSH_FXP_FSTAT 8
 
 /** @brief Set file attributes by name */
-#define SSH_FXP_SETSTAT             9
+#  define SSH_FXP_SETSTAT 9
 
 /** @brief Set file attributes by handle */
-#define SSH_FXP_FSETSTAT           10   /* 0x0A */
+#  define SSH_FXP_FSETSTAT 10 /* 0x0A */
 
 /** @brief Open directory */
-#define SSH_FXP_OPENDIR            11   /* 0x0B */
+#  define SSH_FXP_OPENDIR 11 /* 0x0B */
 
 /** @brief Read from directory */
-#define SSH_FXP_READDIR            12   /* 0x0C */
+#  define SSH_FXP_READDIR 12 /* 0x0C */
 
 /** @brief Remove file */
-#define SSH_FXP_REMOVE             13   /* 0x0D */
+#  define SSH_FXP_REMOVE 13 /* 0x0D */
 
 /** @brief Create directory */
-#define SSH_FXP_MKDIR              14   /* 0x0E */
+#  define SSH_FXP_MKDIR 14 /* 0x0E */
 
 /** @brief Remove directory */
-#define SSH_FXP_RMDIR              15   /* 0x0F */
+#  define SSH_FXP_RMDIR 15 /* 0x0F */
 
 /** @brief Canonicalize path */
-#define SSH_FXP_REALPATH           16   /* 0x10 */
+#  define SSH_FXP_REALPATH 16 /* 0x10 */
 
 /** @brief Get file attributes by name
  *
  * Do follow symlinks.
  */
-#define SSH_FXP_STAT               17   /* 0x11 */
+#  define SSH_FXP_STAT 17 /* 0x11 */
 
 /** @brief Rename file */
-#define SSH_FXP_RENAME             18   /* 0x12 */
+#  define SSH_FXP_RENAME 18 /* 0x12 */
 
 /** @brief Read symbolic link */
-#define SSH_FXP_READLINK           19   /* 0x13 */
+#  define SSH_FXP_READLINK 19 /* 0x13 */
 
 /** @brief Create symbolic link */
-#define SSH_FXP_SYMLINK            20   /* 0x14 */
+#  define SSH_FXP_SYMLINK 20 /* 0x14 */
 
 /** @brief Create hard link */
-#define SSH_FXP_LINK               21   /* 0x15 */
+#  define SSH_FXP_LINK 21 /* 0x15 */
 
 /** @brief Lock byte range */
-#define SSH_FXP_BLOCK              22   /* 0x16 */
+#  define SSH_FXP_BLOCK 22 /* 0x16 */
 
 /** @brief Unlock byte range */
-#define SSH_FXP_UNBLOCK            23   /* 0x17 */
+#  define SSH_FXP_UNBLOCK 23 /* 0x17 */
 
 /** @brief Response with a status */
-#define SSH_FXP_STATUS            101   /* 0x65 */
+#  define SSH_FXP_STATUS 101 /* 0x65 */
 
 /** @brief Response with a handle */
-#define SSH_FXP_HANDLE            102   /* 0x66 */
+#  define SSH_FXP_HANDLE 102 /* 0x66 */
 
 /** @brief Response with data bytes */
-#define SSH_FXP_DATA              103   /* 0x67 */
+#  define SSH_FXP_DATA 103 /* 0x67 */
 
 /** @brief Response with a name */
-#define SSH_FXP_NAME              104   /* 0x68 */
+#  define SSH_FXP_NAME 104 /* 0x68 */
 
 /** @brief Response with attributes */
-#define SSH_FXP_ATTRS             105   /* 0x69 */
+#  define SSH_FXP_ATTRS 105 /* 0x69 */
 
 /** @brief Execute an extended command */
-#define SSH_FXP_EXTENDED          200   /* 0xC8 */
+#  define SSH_FXP_EXTENDED 200 /* 0xC8 */
 
 /** @brief Extended response format */
-#define SSH_FXP_EXTENDED_REPLY    201   /* 0xC9 */
+#  define SSH_FXP_EXTENDED_REPLY 201 /* 0xC9 */
 
 /** @} */
 
-#define SSH_ACL_CAP_ALLOW                       0x00000001
-#define SSH_ACL_CAP_DENY                        0x00000002
-#define SSH_ACL_CAP_AUDIT                       0x00000004
-#define SSH_ACL_CAP_ALARM                       0x00000008
-#define SSH_ACL_CAP_INHERIT_ACCESS              0x00000010
-#define SSH_ACL_CAP_INHERIT_AUDIT_ALARM         0x00000020
+#  define SSH_ACL_CAP_ALLOW 0x00000001
+#  define SSH_ACL_CAP_DENY 0x00000002
+#  define SSH_ACL_CAP_AUDIT 0x00000004
+#  define SSH_ACL_CAP_ALARM 0x00000008
+#  define SSH_ACL_CAP_INHERIT_ACCESS 0x00000010
+#  define SSH_ACL_CAP_INHERIT_AUDIT_ALARM 0x00000020
 
 /** @defgroup valid_attribute_flags SFTP 'valid-attribute-flags' definitions
  * @{
  */
 
 /** @brief @c size field is present */
-#define SSH_FILEXFER_ATTR_SIZE              0x00000001
+#  define SSH_FILEXFER_ATTR_SIZE 0x00000001
 
 /** @brief @c uid and @c gid fiels are present
  *
  * This is for v3 only.
  */
-#define SSH_FILEXFER_ATTR_UIDGID            0x00000002
+#  define SSH_FILEXFER_ATTR_UIDGID 0x00000002
 
 /** @brief @c permissions field is present */
-#define SSH_FILEXFER_ATTR_PERMISSIONS       0x00000004
+#  define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
 
 /** @brief @c atime field is present
  *
  * This is for v4 and later.
  */
-#define SSH_FILEXFER_ATTR_ACCESSTIME        0x00000008
+#  define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008
 
 /** @brief @c atime and @c mtime fiels are present
  *
  * This is for v3 only.
  */
-#define SSH_FILEXFER_ACMODTIME              0x00000008
+#  define SSH_FILEXFER_ACMODTIME 0x00000008
 
 /** @brief @c createtime field is present */
-#define SSH_FILEXFER_ATTR_CREATETIME        0x00000010
+#  define SSH_FILEXFER_ATTR_CREATETIME 0x00000010
 
 /** @brief @c mtime field is present */
-#define SSH_FILEXFER_ATTR_MODIFYTIME        0x00000020
+#  define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020
 
 /** @brief @c ACL field is present */
-#define SSH_FILEXFER_ATTR_ACL               0x00000040
+#  define SSH_FILEXFER_ATTR_ACL 0x00000040
 
 /** @brief @c owner and @c group fields are present */
-#define SSH_FILEXFER_ATTR_OWNERGROUP        0x00000080
+#  define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080
 
 /** @brief Times include subsecond fields */
-#define SSH_FILEXFER_ATTR_SUBSECOND_TIMES   0x00000100
+#  define SSH_FILEXFER_ATTR_SUBSECOND_TIMES 0x00000100
 
 /** @brief @c attrib-bits and @c attrib-bits-valid fields are present */
-#define SSH_FILEXFER_ATTR_BITS              0x00000200
+#  define SSH_FILEXFER_ATTR_BITS 0x00000200
 
 /** @brief @c allocaiton-size field is present */
-#define SSH_FILEXFER_ATTR_ALLOCATION_SIZE   0x00000400
+#  define SSH_FILEXFER_ATTR_ALLOCATION_SIZE 0x00000400
 
 /** @brief @c text-hint field is present */
-#define SSH_FILEXFER_ATTR_TEXT_HINT         0x00000800
+#  define SSH_FILEXFER_ATTR_TEXT_HINT 0x00000800
 
 /** @brief @c mime-type field is present */
-#define SSH_FILEXFER_ATTR_MIME_TYPE         0x00001000
+#  define SSH_FILEXFER_ATTR_MIME_TYPE 0x00001000
 
 /** @brief @c link-count field is present */
-#define SSH_FILEXFER_ATTR_LINK_COUNT        0x00002000
+#  define SSH_FILEXFER_ATTR_LINK_COUNT 0x00002000
 
 /** @brief @c untranslated-name field is present */
-#define SSH_FILEXFER_ATTR_UNTRANSLATED_NAME 0x00004000
+#  define SSH_FILEXFER_ATTR_UNTRANSLATED_NAME 0x00004000
 
 /** @brief @c time field is present */
-#define SSH_FILEXFER_ATTR_CTIME             0x00008000
+#  define SSH_FILEXFER_ATTR_CTIME 0x00008000
 
 /** @brief Extended attributes present */
-#define SSH_FILEXFER_ATTR_EXTENDED          0x80000000
+#  define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
 
 /** @} */
 
@@ -225,111 +229,111 @@
  */
 
 /** @brief Regular file */
-#define SSH_FILEXFER_TYPE_REGULAR          1
+#  define SSH_FILEXFER_TYPE_REGULAR 1
 
 /** @brief Directory */
-#define SSH_FILEXFER_TYPE_DIRECTORY        2
+#  define SSH_FILEXFER_TYPE_DIRECTORY 2
 
 /** @brief Symbolic link */
-#define SSH_FILEXFER_TYPE_SYMLINK          3
+#  define SSH_FILEXFER_TYPE_SYMLINK 3
 
 /** @brief Special file
  *
  * This is for files where the type is known but cannot be exprssed in SFTP. */
-#define SSH_FILEXFER_TYPE_SPECIAL          4
+#  define SSH_FILEXFER_TYPE_SPECIAL 4
 
 /** @brief Unknown file type */
-#define SSH_FILEXFER_TYPE_UNKNOWN          5
+#  define SSH_FILEXFER_TYPE_UNKNOWN 5
 
 /** @brief Socket */
-#define SSH_FILEXFER_TYPE_SOCKET           6
+#  define SSH_FILEXFER_TYPE_SOCKET 6
 
 /** @brief Character device */
-#define SSH_FILEXFER_TYPE_CHAR_DEVICE      7
+#  define SSH_FILEXFER_TYPE_CHAR_DEVICE 7
 
 /** @brief Block device */
-#define SSH_FILEXFER_TYPE_BLOCK_DEVICE     8
+#  define SSH_FILEXFER_TYPE_BLOCK_DEVICE 8
 
 /** @brief Named pipe */
-#define SSH_FILEXFER_TYPE_FIFO             9
+#  define SSH_FILEXFER_TYPE_FIFO 9
 
 /** @} */
 
-#define SFX_ACL_CONTROL_INCLUDED        0x00000001
-#define SFX_ACL_CONTROL_PRESENT         0x00000002
-#define SFX_ACL_CONTROL_INHERITED       0x00000004
-#define SFX_ACL_AUDIT_ALARM_INCLUDED    0x00000010
-
-#define ACE4_ACCESS_ALLOWED_ACE_TYPE 0x00000000
-#define ACE4_ACCESS_DENIED_ACE_TYPE  0x00000001
-#define ACE4_SYSTEM_AUDIT_ACE_TYPE   0x00000002
-#define ACE4_SYSTEM_ALARM_ACE_TYPE   0x00000003
-
-#define ACE4_FILE_INHERIT_ACE           0x00000001
-#define ACE4_DIRECTORY_INHERIT_ACE      0x00000002
-#define ACE4_NO_PROPAGATE_INHERIT_ACE   0x00000004
-#define ACE4_INHERIT_ONLY_ACE           0x00000008
-#define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010
-#define ACE4_FAILED_ACCESS_ACE_FLAG     0x00000020
-#define ACE4_IDENTIFIER_GROUP           0x00000040
-
-#define ACE4_READ_DATA         0x00000001
-#define ACE4_LIST_DIRECTORY    0x00000001
-#define ACE4_WRITE_DATA        0x00000002
-#define ACE4_ADD_FILE          0x00000002
-#define ACE4_APPEND_DATA       0x00000004
-#define ACE4_ADD_SUBDIRECTORY  0x00000004
-#define ACE4_READ_NAMED_ATTRS  0x00000008
-#define ACE4_WRITE_NAMED_ATTRS 0x00000010
-#define ACE4_EXECUTE           0x00000020
-#define ACE4_DELETE_CHILD      0x00000040
-#define ACE4_READ_ATTRIBUTES   0x00000080
-#define ACE4_WRITE_ATTRIBUTES  0x00000100
-#define ACE4_DELETE            0x00010000
-#define ACE4_READ_ACL          0x00020000
-#define ACE4_WRITE_ACL         0x00040000
-#define ACE4_WRITE_OWNER       0x00080000
-#define ACE4_SYNCHRONIZE       0x00100000
+#  define SFX_ACL_CONTROL_INCLUDED 0x00000001
+#  define SFX_ACL_CONTROL_PRESENT 0x00000002
+#  define SFX_ACL_CONTROL_INHERITED 0x00000004
+#  define SFX_ACL_AUDIT_ALARM_INCLUDED 0x00000010
+
+#  define ACE4_ACCESS_ALLOWED_ACE_TYPE 0x00000000
+#  define ACE4_ACCESS_DENIED_ACE_TYPE 0x00000001
+#  define ACE4_SYSTEM_AUDIT_ACE_TYPE 0x00000002
+#  define ACE4_SYSTEM_ALARM_ACE_TYPE 0x00000003
+
+#  define ACE4_FILE_INHERIT_ACE 0x00000001
+#  define ACE4_DIRECTORY_INHERIT_ACE 0x00000002
+#  define ACE4_NO_PROPAGATE_INHERIT_ACE 0x00000004
+#  define ACE4_INHERIT_ONLY_ACE 0x00000008
+#  define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010
+#  define ACE4_FAILED_ACCESS_ACE_FLAG 0x00000020
+#  define ACE4_IDENTIFIER_GROUP 0x00000040
+
+#  define ACE4_READ_DATA 0x00000001
+#  define ACE4_LIST_DIRECTORY 0x00000001
+#  define ACE4_WRITE_DATA 0x00000002
+#  define ACE4_ADD_FILE 0x00000002
+#  define ACE4_APPEND_DATA 0x00000004
+#  define ACE4_ADD_SUBDIRECTORY 0x00000004
+#  define ACE4_READ_NAMED_ATTRS 0x00000008
+#  define ACE4_WRITE_NAMED_ATTRS 0x00000010
+#  define ACE4_EXECUTE 0x00000020
+#  define ACE4_DELETE_CHILD 0x00000040
+#  define ACE4_READ_ATTRIBUTES 0x00000080
+#  define ACE4_WRITE_ATTRIBUTES 0x00000100
+#  define ACE4_DELETE 0x00010000
+#  define ACE4_READ_ACL 0x00020000
+#  define ACE4_WRITE_ACL 0x00040000
+#  define ACE4_WRITE_OWNER 0x00080000
+#  define ACE4_SYNCHRONIZE 0x00100000
 
 /** @defgroup attrib_bits SFTP 'attrib-bits' definitions
  * @{
  */
 
 /** @brief File is read-only (advisory) */
-#define SSH_FILEXFER_ATTR_FLAGS_READONLY         0x00000001
+#  define SSH_FILEXFER_ATTR_FLAGS_READONLY 0x00000001
 
 /** @brief File is part of the OS */
-#define SSH_FILEXFER_ATTR_FLAGS_SYSTEM           0x00000002
+#  define SSH_FILEXFER_ATTR_FLAGS_SYSTEM 0x00000002
 
 /** @brief File is hidden */
-#define SSH_FILEXFER_ATTR_FLAGS_HIDDEN           0x00000004
+#  define SSH_FILEXFER_ATTR_FLAGS_HIDDEN 0x00000004
 
 /** @brief Filenames in this directory are case-insensitive */
-#define SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE 0x00000008
+#  define SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE 0x00000008
 
 /** @brief File should be archived */
-#define SSH_FILEXFER_ATTR_FLAGS_ARCHIVE          0x00000010
+#  define SSH_FILEXFER_ATTR_FLAGS_ARCHIVE 0x00000010
 
 /** @brief File is stored on encrypted media */
-#define SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED        0x00000020
+#  define SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED 0x00000020
 
 /** @brief File is stored on compressed media */
-#define SSH_FILEXFER_ATTR_FLAGS_COMPRESSED       0x00000040
+#  define SSH_FILEXFER_ATTR_FLAGS_COMPRESSED 0x00000040
 
 /** @brief File is sparse */
-#define SSH_FILEXFER_ATTR_FLAGS_SPARSE           0x00000080
+#  define SSH_FILEXFER_ATTR_FLAGS_SPARSE 0x00000080
 
 /** @brief File is append-only */
-#define SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY      0x00000100
+#  define SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY 0x00000100
 
 /** @brief File cannot be delete, renamed, linked to or written */
-#define SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE        0x00000200
+#  define SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE 0x00000200
 
 /** @brief Modifications to file are synchronous */
-#define SSH_FILEXFER_ATTR_FLAGS_SYNC             0x00000400
+#  define SSH_FILEXFER_ATTR_FLAGS_SYNC 0x00000400
 
 /** @brief Filename could not be converted to UTF-8 */
-#define SSH_FILEXFER_ATTR_FLAGS_TRANSLATION_ERR  0x00000800
+#  define SSH_FILEXFER_ATTR_FLAGS_TRANSLATION_ERR 0x00000800
 
 /** @} */
 
@@ -338,16 +342,16 @@
  */
 
 /** @brief Server knows file is a text file */
-#define SSH_FILEXFER_ATTR_KNOWN_TEXT        0x00
+#  define SSH_FILEXFER_ATTR_KNOWN_TEXT 0x00
 
 /** @brief Server believes file is a text file */
-#define SSH_FILEXFER_ATTR_GUESSED_TEXT      0x01
+#  define SSH_FILEXFER_ATTR_GUESSED_TEXT 0x01
 
 /** @brief Server knows file is a binary file */
-#define SSH_FILEXFER_ATTR_KNOWN_BINARY      0x02
+#  define SSH_FILEXFER_ATTR_KNOWN_BINARY 0x02
 
 /** @brief Server believes file is a binary file */
-#define SSH_FILEXFER_ATTR_GUESSED_BINARY    0x03
+#  define SSH_FILEXFER_ATTR_GUESSED_BINARY 0x03
 
 /** @} */
 
@@ -356,61 +360,61 @@
  */
 
 /** @brief Mask of file open bits */
-#define SSH_FXF_ACCESS_DISPOSITION       0x00000007
+#  define SSH_FXF_ACCESS_DISPOSITION 0x00000007
 
 /** @brief Must create a new file */
-#define SSH_FXF_CREATE_NEW           0x00000000
+#  define SSH_FXF_CREATE_NEW 0x00000000
 
 /** @brief Create new file or truncate existing one */
-#define SSH_FXF_CREATE_TRUNCATE      0x00000001
+#  define SSH_FXF_CREATE_TRUNCATE 0x00000001
 
 /** @brief File must already exist */
-#define SSH_FXF_OPEN_EXISTING        0x00000002
+#  define SSH_FXF_OPEN_EXISTING 0x00000002
 
 /** @brief Open existing file or create new one */
-#define SSH_FXF_OPEN_OR_CREATE       0x00000003
+#  define SSH_FXF_OPEN_OR_CREATE 0x00000003
 
 /** @brief Truncate an existing file */
-#define SSH_FXF_TRUNCATE_EXISTING    0x00000004
+#  define SSH_FXF_TRUNCATE_EXISTING 0x00000004
 
 /** @brief Lossy append only */
-#define SSH_FXF_APPEND_DATA              0x00000008
+#  define SSH_FXF_APPEND_DATA 0x00000008
 
 /** @brief Append only */
-#define SSH_FXF_APPEND_DATA_ATOMIC       0x00000010
+#  define SSH_FXF_APPEND_DATA_ATOMIC 0x00000010
 
 /** @brief Convert newlines */
-#define SSH_FXF_TEXT_MODE                0x00000020
+#  define SSH_FXF_TEXT_MODE 0x00000020
 
 /** @brief Exclusive read access */
-#define SSH_FXF_BLOCK_READ               0x00000040
+#  define SSH_FXF_BLOCK_READ 0x00000040
 
 /** @brief Exclusive write access */
-#define SSH_FXF_BLOCK_WRITE              0x00000080
+#  define SSH_FXF_BLOCK_WRITE 0x00000080
 
 /** @brief Exclusive delete access */
-#define SSH_FXF_BLOCK_DELETE             0x00000100
+#  define SSH_FXF_BLOCK_DELETE 0x00000100
 
 /** @brief Other @c SSH_FXF_BLOCK_... bits are advisory */
-#define SSH_FXF_BLOCK_ADVISORY           0x00000200
+#  define SSH_FXF_BLOCK_ADVISORY 0x00000200
 
 /** @brief Do not follow symlinks */
-#define SSH_FXF_NOFOLLOW                 0x00000400
+#  define SSH_FXF_NOFOLLOW 0x00000400
 
 /** @brief Delete when last handle closed */
-#define SSH_FXF_DELETE_ON_CLOSE          0x00000800
+#  define SSH_FXF_DELETE_ON_CLOSE 0x00000800
 
 /** @brief Enable audit/alarm privileges */
-#define SSH_FXF_ACCESS_AUDIT_ALARM_INFO  0x00001000
+#  define SSH_FXF_ACCESS_AUDIT_ALARM_INFO 0x00001000
 
 /** @brief Enable backup privileges */
-#define SSH_FXF_ACCESS_BACKUP            0x00002000
+#  define SSH_FXF_ACCESS_BACKUP 0x00002000
 
 /** @brief Read or write backup stream */
-#define SSH_FXF_BACKUP_STREAM            0x00004000
+#  define SSH_FXF_BACKUP_STREAM 0x00004000
 
 /** @brief Enable owner privileges */
-#define SSH_FXF_OVERRIDE_OWNER           0x00008000
+#  define SSH_FXF_OVERRIDE_OWNER 0x00008000
 
 /** @} */
 
@@ -419,13 +423,14 @@
  */
 
 /** @brief Overwrite target if it exists */
-#define SSH_FXF_RENAME_OVERWRITE  0x00000001
+#  define SSH_FXF_RENAME_OVERWRITE 0x00000001
 
-/** @brief Ensure target name always exists and refers to original or new file */
-#define SSH_FXF_RENAME_ATOMIC     0x00000002
+/** @brief Ensure target name always exists and refers to original or new file
+ */
+#  define SSH_FXF_RENAME_ATOMIC 0x00000002
 
 /** @brief Remove requirements on server */
-#define SSH_FXF_RENAME_NATIVE     0x00000004
+#  define SSH_FXF_RENAME_NATIVE 0x00000004
 
 /** @} */
 
@@ -434,13 +439,13 @@
  */
 
 /** @brief Don't check for existence or accessibility, don't resolve links */
-#define SSH_FXP_REALPATH_NO_CHECK    0x00000001
+#  define SSH_FXP_REALPATH_NO_CHECK 0x00000001
 
 /** @brief Get file attribtues if it exists */
-#define SSH_FXP_REALPATH_STAT_IF     0x00000002
+#  define SSH_FXP_REALPATH_STAT_IF 0x00000002
 
 /** @brief Get file attributes, fail if unavailable */
-#define SSH_FXP_REALPATH_STAT_ALWAYS 0x00000003
+#  define SSH_FXP_REALPATH_STAT_ALWAYS 0x00000003
 
 /** @} */
 
@@ -449,25 +454,25 @@
  */
 
 /** @brief Open file for reading */
-#define SSH_FXF_READ            0x00000001
+#  define SSH_FXF_READ 0x00000001
 
 /** @brief Open file for writing */
-#define SSH_FXF_WRITE           0x00000002
+#  define SSH_FXF_WRITE 0x00000002
 
 /** @brief Append to end of file */
-#define SSH_FXF_APPEND          0x00000004
+#  define SSH_FXF_APPEND 0x00000004
 
 /** @brief Create file if it does not exist */
-#define SSH_FXF_CREAT           0x00000008
+#  define SSH_FXF_CREAT 0x00000008
 
 /** @brief Truncate file if it already exists */
-#define SSH_FXF_TRUNC           0x00000010
+#  define SSH_FXF_TRUNC 0x00000010
 
 /** @brief File must not exist */
-#define SSH_FXF_EXCL            0x00000020
+#  define SSH_FXF_EXCL 0x00000020
 
 /** @brief Convert newlines */
-#define SSH_FXF_TEXT            0x00000040
+#  define SSH_FXF_TEXT 0x00000040
 
 /** @} */
 
@@ -476,100 +481,100 @@
  */
 
 /** @brief Success */
-#define SSH_FX_OK                            0
+#  define SSH_FX_OK 0
 
 /** @brief End of file */
-#define SSH_FX_EOF                           1
+#  define SSH_FX_EOF 1
 
 /** @brief File does not exist */
-#define SSH_FX_NO_SUCH_FILE                  2
+#  define SSH_FX_NO_SUCH_FILE 2
 
 /** @brief Insufficient permission */
-#define SSH_FX_PERMISSION_DENIED             3
+#  define SSH_FX_PERMISSION_DENIED 3
 
 /** @brief Unknown error */
-#define SSH_FX_FAILURE                       4
+#  define SSH_FX_FAILURE 4
 
 /** @brief Badly formatted packet */
-#define SSH_FX_BAD_MESSAGE                   5
+#  define SSH_FX_BAD_MESSAGE 5
 
 /** @brief No connection to server */
-#define SSH_FX_NO_CONNECTION                 6
+#  define SSH_FX_NO_CONNECTION 6
 
 /** @brief Connection to server lost */
-#define SSH_FX_CONNECTION_LOST               7
+#  define SSH_FX_CONNECTION_LOST 7
 
 /** @brief Operation not supported by server */
-#define SSH_FX_OP_UNSUPPORTED                8
+#  define SSH_FX_OP_UNSUPPORTED 8
 
 /** @brief Invalid handle value */
-#define SSH_FX_INVALID_HANDLE                9  /*      v4+ */
+#  define SSH_FX_INVALID_HANDLE 9 /*      v4+ */
 
 /** @brief File path does not exist or is invalid */
-#define SSH_FX_NO_SUCH_PATH                  10 /* 0x0A */
+#  define SSH_FX_NO_SUCH_PATH 10 /* 0x0A */
 
 /** @brief File already exists */
-#define SSH_FX_FILE_ALREADY_EXISTS           11 /* 0x0B */
+#  define SSH_FX_FILE_ALREADY_EXISTS 11 /* 0x0B */
 
 /** @brief File is on read-only or write-protected media */
-#define SSH_FX_WRITE_PROTECT                 12 /* 0x0C */
+#  define SSH_FX_WRITE_PROTECT 12 /* 0x0C */
 
 /** @brief No medium in drive */
-#define SSH_FX_NO_MEDIA                      13 /* 0x0D */
+#  define SSH_FX_NO_MEDIA 13 /* 0x0D */
 
 /** @brief Insufficient free space */
-#define SSH_FX_NO_SPACE_ON_FILESYSTEM        14 /* 0x0E v5+ */
+#  define SSH_FX_NO_SPACE_ON_FILESYSTEM 14 /* 0x0E v5+ */
 
 /** @brief User's storage quota would be exceeded */
-#define SSH_FX_QUOTA_EXCEEDED                15 /* 0x0F */
+#  define SSH_FX_QUOTA_EXCEEDED 15 /* 0x0F */
 
 /** @brief Unknown principal in ACL */
-#define SSH_FX_UNKNOWN_PRINCIPAL             16 /* 0x10 */
+#  define SSH_FX_UNKNOWN_PRINCIPAL 16 /* 0x10 */
 
 /** @brief File is locked by another process */
-#define SSH_FX_LOCK_CONFLICT                 17 /* 0x11 */
+#  define SSH_FX_LOCK_CONFLICT 17 /* 0x11 */
 
 /** @brief Directory is not empty */
-#define SSH_FX_DIR_NOT_EMPTY                 18 /* 0x12 v6+ */
+#  define SSH_FX_DIR_NOT_EMPTY 18 /* 0x12 v6+ */
 
 /** @brief File is not a director */
-#define SSH_FX_NOT_A_DIRECTORY               19 /* 0x13 */
+#  define SSH_FX_NOT_A_DIRECTORY 19 /* 0x13 */
 
 /** @brief Filename is invalid */
-#define SSH_FX_INVALID_FILENAME              20 /* 0x14 */
+#  define SSH_FX_INVALID_FILENAME 20 /* 0x14 */
 
 /** @brief Too many symbolic links or link found by @ref SSH_FXF_NOFOLLOW */
-#define SSH_FX_LINK_LOOP                     21 /* 0x15 */
+#  define SSH_FX_LINK_LOOP 21 /* 0x15 */
 
 /** @brief File cannot be deleted */
-#define SSH_FX_CANNOT_DELETE                 22 /* 0x16 */
+#  define SSH_FX_CANNOT_DELETE 22 /* 0x16 */
 
 /** @brief Parameter out of range or conflicting */
-#define SSH_FX_INVALID_PARAMETER             23 /* 0x17 */
+#  define SSH_FX_INVALID_PARAMETER 23 /* 0x17 */
 
 /** @brief File is a directory */
-#define SSH_FX_FILE_IS_A_DIRECTORY           24 /* 0x18 */
+#  define SSH_FX_FILE_IS_A_DIRECTORY 24 /* 0x18 */
 
 /** @brief Mandatory lock conflict when reading or writing */
-#define SSH_FX_BYTE_RANGE_LOCK_CONFLICT      25 /* 0x19 */
+#  define SSH_FX_BYTE_RANGE_LOCK_CONFLICT 25 /* 0x19 */
 
 /** @brief Lock request refused */
-#define SSH_FX_BYTE_RANGE_LOCK_REFUSED       26 /* 0x1A */
+#  define SSH_FX_BYTE_RANGE_LOCK_REFUSED 26 /* 0x1A */
 
 /** @brief Delete operation pending on faile */
-#define SSH_FX_DELETE_PENDING                27 /* 0x1B */
+#  define SSH_FX_DELETE_PENDING 27 /* 0x1B */
 
 /** @brief File is corrupt */
-#define SSH_FX_FILE_CORRUPT                  28 /* 0x1C */
+#  define SSH_FX_FILE_CORRUPT 28 /* 0x1C */
 
 /** @brief Principal cannot become file owner */
-#define SSH_FX_OWNER_INVALID                 29 /* 0x1D */
+#  define SSH_FX_OWNER_INVALID 29 /* 0x1D */
 
 /** @brief Principal cannot become file group */
-#define SSH_FX_GROUP_INVALID                 30 /* 0x1E */
+#  define SSH_FX_GROUP_INVALID 30 /* 0x1E */
 
 /** @brief Specified lock range has not been granted */
-#define SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK   31 /* 0x1F */
+#  define SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK 31 /* 0x1F */
 
 /** @} */
 
@@ -619,10 +624,14 @@
  * @section specs Specifications
  *
  * - http://www.ietf.org/rfc/rfc4251.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-02.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-04.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05.txt
- * - http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-13.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-02.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-04.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05.txt
+ * -
+ * http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-13.txt
  *
  * @section links Links
  *
diff --git a/sftpclient.c b/sftpclient.c
old mode 100755
new mode 100644
index 1092bd7..3d998e7
--- a/sftpclient.c
+++ b/sftpclient.c
@@ -56,8 +56,8 @@
 #include <limits.h>
 #include <termios.h>
 #if HAVE_READLINE
-# include <readline/readline.h>
-# include <readline/history.h>
+#  include <readline/readline.h>
+#  include <readline/history.h>
 #endif
 
 struct command {
@@ -116,75 +116,76 @@ static int forceversion;
 static char *sftp_realpath(const char *path);
 
 static const struct option options[] = {
-  { "help", no_argument, 0, 'h' },
-  { "version", no_argument, 0, 'V' },
-  { "dropbear", no_argument, 0, 'r' },
-  { "buffer", required_argument, 0, 'B' },
-  { "batch", required_argument, 0, 'b' },
-  { "program", required_argument, 0, 'P' },
-  { "requests", required_argument, 0, 'R' },
-  { "subsystem", required_argument, 0, 's' },
-  { "sftp-version", required_argument, 0, 'S' },
-  { "quirk-reverse-symlink", no_argument, 0, 256 },
-  { "stop-on-error", no_argument, 0, 257 },
-  { "no-stop-on-error", no_argument, 0, 258 },
-  { "progress", no_argument, 0, 259 },
-  { "no-progress", no_argument, 0, 260 },
-  { "echo", no_argument, 0, 261 },
-  { "fix-sigpipe", no_argument, 0, 262 },
-  { "force-version", required_argument, 0, 263 },
-  { "debug", no_argument, 0, 'd' },
-  { "debug-path", required_argument, 0, 'D' },
-  { "program-debug-path", required_argument, 0, 264 },
-  { "host", required_argument, 0, 'H' },
-  { "port", required_argument, 0, 'p' },
-  { "ipv4", no_argument, 0, '4' },
-  { "ipv6", no_argument, 0, '6' },
-  { "1", no_argument, 0, '1' },
-  { "2", no_argument, 0, '2' },
-  { "C", no_argument, 0, 'C' },
-  { "F", required_argument, 0, 'F' },
-  { "o", required_argument, 0, 'o' },
-  { "v", no_argument, 0, 'v' },
-  { 0, 0, 0, 0 }
-};
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"dropbear", no_argument, 0, 'r'},
+    {"buffer", required_argument, 0, 'B'},
+    {"batch", required_argument, 0, 'b'},
+    {"program", required_argument, 0, 'P'},
+    {"requests", required_argument, 0, 'R'},
+    {"subsystem", required_argument, 0, 's'},
+    {"sftp-version", required_argument, 0, 'S'},
+    {"quirk-reverse-symlink", no_argument, 0, 256},
+    {"stop-on-error", no_argument, 0, 257},
+    {"no-stop-on-error", no_argument, 0, 258},
+    {"progress", no_argument, 0, 259},
+    {"no-progress", no_argument, 0, 260},
+    {"echo", no_argument, 0, 261},
+    {"fix-sigpipe", no_argument, 0, 262},
+    {"force-version", required_argument, 0, 263},
+    {"debug", no_argument, 0, 'd'},
+    {"debug-path", required_argument, 0, 'D'},
+    {"program-debug-path", required_argument, 0, 264},
+    {"host", required_argument, 0, 'H'},
+    {"port", required_argument, 0, 'p'},
+    {"ipv4", no_argument, 0, '4'},
+    {"ipv6", no_argument, 0, '6'},
+    {"1", no_argument, 0, '1'},
+    {"2", no_argument, 0, '2'},
+    {"C", no_argument, 0, 'C'},
+    {"F", required_argument, 0, 'F'},
+    {"o", required_argument, 0, 'o'},
+    {"v", no_argument, 0, 'v'},
+    {0, 0, 0, 0}};
 
 /* display usage message and terminate */
 static void attribute((noreturn)) help(void) {
-  xprintf("Usage:\n"
-          "  sftpclient [OPTIONS] [USER@]HOST\n"
-          "\n"
-          "Quick and dirty SFTP client\n"
-          "\n");
-  xprintf("Options:\n"
-          "  --help, -h               Display usage message\n"
-          "  --version, -V            Display version number\n"
-          "  -r, --dropbear           Use dbclient instead of ssh\n"
-          "  -B, --buffer BYTES       Select buffer size (default 8192)\n"
-          "  -b, --batch PATH         Read batch file\n"
-          "  -P, --program PATH       Execute program as SFTP server\n");
-  xprintf("  -R, --requests COUNT     Maximum outstanding requests (default 8)\n"
-          "  -s, --subsystem NAME     Remote subsystem name\n"
-          "  -S, --sftp-version VER   Protocol version to request (default 3)\n"
-          "  --quirk-openssh          Server gets SSH_FXP_SYMLINK backwards\n");
-  xprintf("Options passed to SSH:\n"
-          "  -1, -2                   Select protocol version\n"
-          "  -C                       Enable compression\n"
-          "  -F PATH                  Use alternative  config file\n"
-          "  -o OPTION                Pass option to client\n"
-          "  -v                       Raise logging level\n");
+  sftp_xprintf("Usage:\n"
+               "  sftpclient [OPTIONS] [USER@]HOST\n"
+               "\n"
+               "Quick and dirty SFTP client\n"
+               "\n");
+  sftp_xprintf(
+      "Options:\n"
+      "  --help, -h               Display usage message\n"
+      "  --version, -V            Display version number\n"
+      "  -r, --dropbear           Use dbclient instead of ssh\n"
+      "  -B, --buffer BYTES       Select buffer size (default 8192)\n"
+      "  -b, --batch PATH         Read batch file\n"
+      "  -P, --program PATH       Execute program as SFTP server\n"
+      "  -R, --requests COUNT     Maximum outstanding requests (default 8)\n"
+      "  -s, --subsystem NAME     Remote subsystem name\n"
+      "  -S, --sftp-version VER   Protocol version to request (default 3)\n"
+      "  --echo                   Echo commands\n"
+      "  --quirk-openssh          Server gets SSH_FXP_SYMLINK backwards\n"
+      "Options passed to SSH:\n"
+      "  -1, -2                   Select protocol version\n"
+      "  -C                       Enable compression\n"
+      "  -F PATH                  Use alternative  config file\n"
+      "  -o OPTION                Pass option to client\n"
+      "  -v                       Raise logging level\n");
   exit(0);
 }
 
 /* display version number and terminate */
 static void attribute((noreturn)) version(void) {
-  xprintf("sftp client version %s\n", VERSION);
+  sftp_xprintf("sftp client version %s\n", VERSION);
   exit(0);
 }
 
 /* Utilities */
 
-static int attribute((format(printf,1,2))) error(const char *fmt, ...) {
+static int attribute((format(printf, 1, 2))) error(const char *fmt, ...) {
   va_list ap;
 
   if(inputpath)
@@ -192,7 +193,7 @@ static int attribute((format(printf,1,2))) error(const char *fmt, ...) {
   va_start(ap, fmt);
   vfprintf(stderr, fmt, ap);
   va_end(ap);
-  fputc('\n',  stderr);
+  fputc('\n', stderr);
   fflush(stderr);
   return -1;
 }
@@ -200,7 +201,7 @@ static int attribute((format(printf,1,2))) error(const char *fmt, ...) {
 static int status(void) {
   uint32_t status;
   char *msg;
-  
+
   /* Cope with half-parsed responses */
   fakejob.ptr = fakejob.data + 5;
   fakejob.left = fakejob.len - 5;
@@ -219,13 +220,15 @@ static uint8_t getresponse(int expected, uint32_t expected_id,
   uint32_t len;
   uint8_t type;
 
-  if(do_read(sftpin, &len, sizeof len))
-    fatal("unexpected EOF from server while reading %s response length", what);
-  free(fakejob.data);                   /* free last job */
+  if(sftp_xread(sftpin, &len, sizeof len))
+    sftp_fatal("unexpected EOF from server while reading %s response length",
+               what);
+  free(fakejob.data); /* free last job */
   fakejob.len = ntohl(len);
-  fakejob.data = xmalloc(fakejob.len);
-  if(do_read(sftpin, fakejob.data, fakejob.len))
-    fatal("unexpected EOF from server while reading %s response data", what);
+  fakejob.data = sftp_xmalloc(fakejob.len);
+  if(sftp_xread(sftpin, fakejob.data, fakejob.len))
+    sftp_fatal("unexpected EOF from server while reading %s response data",
+               what);
   if(sftp_debugging) {
     D(("%s response:", what));
     sftp_debug_hexdump(fakejob.data, fakejob.len);
@@ -236,15 +239,15 @@ static uint8_t getresponse(int expected, uint32_t expected_id,
   if(type != SSH_FXP_VERSION) {
     cpcheck(sftp_parse_uint32(&fakejob, &fakejob.id));
     if(expected_id && fakejob.id != expected_id)
-      fatal("wrong ID in response to %s (want %"PRIu32
-            " got %"PRIu32" type was %d)",
-            what, expected_id, fakejob.id, type);
+      sftp_fatal("wrong ID in response to %s (want %" PRIu32 " got %" PRIu32
+                 " type was %d)",
+                 what, expected_id, fakejob.id, type);
   }
   if(expected > 0 && type != expected) {
     if(type == SSH_FXP_STATUS)
       status();
     else
-      fatal("expected %s response %d got %d", what, expected, type);
+      sftp_fatal("expected %s response %d got %d", what, expected, type);
   }
   return type;
 }
@@ -262,22 +265,22 @@ static int split(char *line, char **av) {
     if(*line == '"') {
       arg = av[ac++] = line++;
       while(*line && *line != '"') {
-	if(*line == '\\' && line[1])
-	  ++line;
-	*arg++ = *line++;
+        if(*line == '\\' && line[1])
+          ++line;
+        *arg++ = *line++;
       }
       if(!*line) {
-	error("unterminated string");
-	return -1;
+        error("unterminated string");
+        return -1;
       }
       *arg++ = 0;
       line++;
     } else {
       av[ac++] = line;
       while(*line && !isspace((unsigned char)*line))
-	++line;
+        ++line;
       if(*line)
-	*line++ = 0;
+        *line++ = 0;
     }
   }
   av[ac] = 0;
@@ -298,7 +301,7 @@ static char *remote_cwd(void) {
   if(!cwd) {
     if(!(cwd = sftp_realpath(".")))
       exit(1);
-    cwd = xstrdup(cwd);
+    cwd = sftp_xstrdup(cwd);
   }
   return cwd;
 }
@@ -306,14 +309,14 @@ static char *remote_cwd(void) {
 static void progress(const char *path, uint64_t sofar, uint64_t total) {
   if(progress_indicators) {
     if(!total)
-      xprintf("\r%*s\r", terminal_width, "");
+      sftp_xprintf("\r%*s\r", terminal_width, "");
     else if(total == (uint64_t)-1)
-      xprintf("\r%.60s: %12"PRIu64"b", path, sofar);
+      sftp_xprintf("\r%.60s: %12" PRIu64 "b", path, sofar);
     else
-      xprintf("\r%.60s: %12"PRIu64"b %3d%%",
-              path, sofar, (int)(100 * sofar / total));
-    if(fflush(stdout) < 0) 
-      fatal("error writing to stdout: %s", strerror(errno));
+      sftp_xprintf("\r%.60s: %12" PRIu64 "b %3d%%", path, sofar,
+                   (int)(100 * sofar / total));
+    if(fflush(stdout) < 0)
+      sftp_fatal("error writing to stdout: %s", strerror(errno));
   }
 }
 
@@ -322,13 +325,13 @@ static void progress(const char *path, uint64_t sofar, uint64_t total) {
 static int sftp_init(void) {
   uint32_t version, u32;
   uint16_t u16;
-  
+
   /* Send SSH_FXP_INIT */
   sftp_send_begin(&fakeworker);
   sftp_send_uint8(&fakeworker, SSH_FXP_INIT);
   sftp_send_uint32(&fakeworker, sftpversion);
   sftp_send_end(&fakeworker);
-  
+
   /* Parse the version reponse */
   if(getresponse(SSH_FXP_VERSION, 0, "SSH_FXP_INIT") != SSH_FXP_VERSION)
     return -1;
@@ -347,7 +350,7 @@ static int sftp_init(void) {
     protocol = &sftp_v6;
     break;
   default:
-    return error("server wanted protocol version %"PRIu32, version);
+    return error("server wanted protocol version %" PRIu32, version);
   }
   attrmask = protocol->attrmask;
   /* Extension data */
@@ -361,14 +364,14 @@ static int sftp_init(void) {
     /* TODO table-driven extension parsing */
     if(!strcmp(xname, "newline")) {
       free(newline);
-      newline = xstrdup(xdata);
+      newline = sftp_xstrdup(xdata);
       if(!*newline)
         return error("cannot cope with empty newline sequence");
       /* TODO check newline sequence doesn't contain repeats */
     } else if(!strcmp(xname, "vendor-id")) {
       struct sftpjob xjob;
-      char *vn ,*sn, *sv;
-      
+      char *vn, *sn, *sv;
+
       xjob.a = &allocator;
       xjob.ptr = (void *)xdata;
       xjob.left = xdatalen;
@@ -377,17 +380,17 @@ static int sftp_init(void) {
       cpcheck(sftp_parse_string(&xjob, &sv, 0));
       cpcheck(sftp_parse_uint64(&xjob, &serverbuild));
       free(vendorname);
-      vendorname = xstrdup(vn);
+      vendorname = sftp_xstrdup(vn);
       free(servername);
-      servername = xstrdup(sn);
+      servername = sftp_xstrdup(sn);
       free(serverversion);
-      serverversion = xstrdup(sv);
+      serverversion = sftp_xstrdup(sv);
     } else if(!strcmp(xname, "versions")) {
       free(serverversions);
-      serverversions = xstrdup(xdata);
+      serverversions = sftp_xstrdup(xdata);
     } else if(!strcmp(xname, "symlink-order@rjk.greenend.org.uk")) {
       /* See commentary in v3.c */
-      if(!strcmp(xdata,  "targetpath-linkpath"))
+      if(!strcmp(xdata, "targetpath-linkpath"))
         quirk_reverse_symlink = 1;
       else if(!strcmp(xdata, "linkpath-targetpath"))
         quirk_reverse_symlink = 0;
@@ -395,7 +398,7 @@ static int sftp_init(void) {
         error("unknown %s value '%s'", xname, xdata);
     } else if(!strcmp(xname, "supported")) {
       struct sftpjob xjob;
-      
+
       xjob.a = &allocator;
       xjob.ptr = (void *)xdata;
       xjob.left = xdatalen;
@@ -408,11 +411,12 @@ static int sftp_init(void) {
         cpcheck(sftp_parse_string(&xjob, 0, 0)); /* extension-names */
     } else if(!strcmp(xname, "supported2")) {
       struct sftpjob xjob;
-      
+
       xjob.a = &allocator;
       xjob.ptr = (void *)xdata;
       xjob.left = xdatalen;
-      cpcheck(sftp_parse_uint32(&xjob, &attrmask)); /* supported-attribute-mask */
+      cpcheck(
+          sftp_parse_uint32(&xjob, &attrmask)); /* supported-attribute-mask */
       assert(!(attrmask & SSH_FILEXFER_ATTR_CTIME));
       cpcheck(sftp_parse_uint32(&xjob, &u32)); /* supported-attribute-bits */
       cpcheck(sftp_parse_uint32(&xjob, &u32)); /* supported-open-flags */
@@ -430,17 +434,14 @@ static int sftp_init(void) {
         cpcheck(sftp_parse_string(&xjob, 0, 0)); /* extension-names */
         --u32;
       }
-    } else if(!strcmp(xname, "posix-rename@openssh.com")
-              && !strcmp(xdata, "1")) {
+    } else if(!strcmp(xname, "posix-rename@openssh.com") &&
+              !strcmp(xdata, "1")) {
       rename_extension = "posix-rename@openssh.com";
-    } else if(!strcmp(xname, "posix-rename@openssh.org")
-              && !rename_extension) {
+    } else if(!strcmp(xname, "posix-rename@openssh.org") && !rename_extension) {
       rename_extension = "posix-rename@openssh.com";
-    } else if(!strcmp(xname, "hardlink@openssh.com")
-              && !strcmp(xdata, "1")) {
+    } else if(!strcmp(xname, "hardlink@openssh.com") && !strcmp(xdata, "1")) {
       hardlink_extension = "hardlink@openssh.com";
-    } else if(!strcmp(xname, "statvfs@openssh.com")
-              && !strcmp(xdata, "2")) {
+    } else if(!strcmp(xname, "statvfs@openssh.com") && !strcmp(xdata, "2")) {
       statvfs_extension = "statvfs@openssh.com";
     }
   }
@@ -463,15 +464,13 @@ static char *sftp_realpath(const char *path) {
     return 0;
   cpcheck(sftp_parse_uint32(&fakejob, &u32));
   if(u32 != 1)
-    fatal("wrong count in SSH_FXP_REALPATH reply");
+    sftp_fatal("wrong count in SSH_FXP_REALPATH reply");
   cpcheck(sftp_parse_path(&fakejob, &resolved));
   return resolved;
 }
 
-static char *sftp_realpath_v6(const char *path,
-                              int control_byte,
-                              char **compose,
-                              struct sftpattr *attrs) {
+static char *sftp_realpath_v6(const char *path, int control_byte,
+                              char **compose, struct sftpattr *attrs) {
   char *resolved;
   uint32_t u32, id;
 
@@ -490,14 +489,13 @@ static char *sftp_realpath_v6(const char *path,
     return 0;
   cpcheck(sftp_parse_uint32(&fakejob, &u32));
   if(u32 != 1)
-    fatal("wrong count in SSH_FXP_REALPATH reply");
+    sftp_fatal("wrong count in SSH_FXP_REALPATH reply");
   cpcheck(sftp_parse_path(&fakejob, &resolved));
   cpcheck(protocol->parseattrs(&fakejob, attrs));
   return resolved;
 }
 
-static int sftp_stat(const char *path, struct sftpattr *attrs,
-                     uint8_t type) {
+static int sftp_stat(const char *path, struct sftpattr *attrs, uint8_t type) {
   uint32_t id;
 
   remote_cwd();
@@ -547,8 +545,7 @@ static int sftp_opendir(const char *path, struct client_handle *hp) {
 }
 
 static int sftp_readdir(const struct client_handle *hp,
-                        struct sftpattr **attrsp,
-                        size_t *nattrsp) {
+                        struct sftpattr **attrsp, size_t *nattrsp) {
   uint32_t id, n;
   struct sftpattr *attrs;
   char *name, *longname = 0;
@@ -562,7 +559,7 @@ static int sftp_readdir(const struct client_handle *hp,
   case SSH_FXP_NAME:
     cpcheck(sftp_parse_uint32(&fakejob, &n));
     if(n > SIZE_MAX / sizeof(struct sftpattr))
-      fatal("too many attributes in SSH_FXP_READDIR response");
+      sftp_fatal("too many attributes in SSH_FXP_READDIR response");
     attrs = sftp_alloc(fakejob.a, n * sizeof(struct sftpattr));
     if(nattrsp)
       *nattrsp = n;
@@ -591,7 +588,7 @@ static int sftp_readdir(const struct client_handle *hp,
     status();
     return -1;
   default:
-    fatal("bogus response to SSH_FXP_READDIR");
+    sftp_fatal("bogus response to SSH_FXP_READDIR");
   }
 }
 
@@ -607,8 +604,7 @@ static int sftp_close(const struct client_handle *hp) {
   return status();
 }
 
-static int sftp_setstat(const char *path,
-                        const struct sftpattr *attrs) {
+static int sftp_setstat(const char *path, const struct sftpattr *attrs) {
   uint32_t id;
 
   remote_cwd();
@@ -662,15 +658,15 @@ static int sftp_remove(const char *path) {
   return status();
 }
 
-static int sftp_rename(const char *oldpath, const char *newpath, 
+static int sftp_rename(const char *oldpath, const char *newpath,
                        unsigned flags) {
   uint32_t id;
-  
+
   remote_cwd();
   /* In v3/4 atomic is assumed, overwrite and native are not available */
-  if(protocol->version <= 4 && (flags & ~SSH_FXF_RENAME_ATOMIC) != 0)
-    return error("cannot emulate rename flags %#x in protocol %d",
-                 flags, protocol->version);
+  if(protocol->version <= 4 && (flags & (uint32_t)~SSH_FXF_RENAME_ATOMIC) != 0)
+    return error("cannot emulate rename flags %#x in protocol %d", flags,
+                 protocol->version);
   sftp_send_begin(&fakeworker);
   sftp_send_uint8(&fakeworker, SSH_FXP_RENAME);
   sftp_send_uint32(&fakeworker, id = newid());
@@ -685,7 +681,7 @@ static int sftp_rename(const char *oldpath, const char *newpath,
 
 static int sftp_prename(const char *oldpath, const char *newpath) {
   uint32_t id;
-  
+
   remote_cwd();
   if(!rename_extension)
     return error("no posix-rename extension found");
@@ -720,18 +716,17 @@ static int sftp_hardlink(const char *targetpath, const char *linkpath) {
 static int sftp_link(const char *targetpath, const char *linkpath,
                      int sftp_send_symlink) {
   uint32_t id;
-  
+
   if(protocol->version < 6 && !sftp_send_symlink) {
     if(hardlink_extension)
       return sftp_hardlink(targetpath, linkpath);
-    return error("hard links not supported in protocol %"PRIu32,
+    return error("hard links not supported in protocol %" PRIu32,
                  protocol->version);
   }
   remote_cwd();
   sftp_send_begin(&fakeworker);
-  sftp_send_uint8(&fakeworker, (protocol->version >= 6
-                           ? SSH_FXP_LINK
-                           : SSH_FXP_SYMLINK));
+  sftp_send_uint8(&fakeworker,
+                  (protocol->version >= 6 ? SSH_FXP_LINK : SSH_FXP_SYMLINK));
   sftp_send_uint32(&fakeworker, id = newid());
   if(quirk_reverse_symlink) {
     /* OpenSSH server gets SSH_FXP_SYMLINK args back to front
@@ -749,10 +744,8 @@ static int sftp_link(const char *targetpath, const char *linkpath,
   return status();
 }
 
-static int sftp_open(const char *path, 
-                     uint32_t desired_access, uint32_t flags,
-                     const struct sftpattr *attrs,
-                     struct client_handle *hp) {
+static int sftp_open(const char *path, uint32_t desired_access, uint32_t flags,
+                     const struct sftpattr *attrs, struct client_handle *hp) {
   uint32_t id, pflags = 0;
 
   remote_cwd();
@@ -764,10 +757,10 @@ static int sftp_open(const char *path,
       pflags |= SSH_FXF_WRITE;
     switch(flags & SSH_FXF_ACCESS_DISPOSITION) {
     case SSH_FXF_CREATE_NEW:
-      pflags |= SSH_FXF_CREAT|SSH_FXF_EXCL;
+      pflags |= SSH_FXF_CREAT | SSH_FXF_EXCL;
       break;
     case SSH_FXF_CREATE_TRUNCATE:
-      pflags |= SSH_FXF_CREAT|SSH_FXF_TRUNC;
+      pflags |= SSH_FXF_CREAT | SSH_FXF_TRUNC;
       break;
     case SSH_FXF_OPEN_OR_CREATE:
       pflags |= SSH_FXF_CREAT;
@@ -778,10 +771,9 @@ static int sftp_open(const char *path,
       pflags |= SSH_FXF_TRUNC;
       break;
     default:
-      return error("unknown SSH_FXF_ACCESS_DISPOSITION %#"PRIx32,
-                   flags);
+      return error("unknown SSH_FXF_ACCESS_DISPOSITION %#" PRIx32, flags);
     }
-    if(flags & (SSH_FXF_APPEND_DATA|SSH_FXF_APPEND_DATA_ATOMIC))
+    if(flags & (SSH_FXF_APPEND_DATA | SSH_FXF_APPEND_DATA_ATOMIC))
       pflags |= SSH_FXF_APPEND;
     if(flags & SSH_FXF_TEXT_MODE) {
       if(protocol->version < 4)
@@ -790,11 +782,10 @@ static int sftp_open(const char *path,
       else
         pflags |= SSH_FXF_TEXT;
     }
-    if(flags & ~(SSH_FXF_ACCESS_DISPOSITION
-                 |SSH_FXF_APPEND_DATA
-                 |SSH_FXF_APPEND_DATA_ATOMIC
-                 |SSH_FXF_TEXT_MODE)) 
-      return error("future SSH_FXP_OPEN flags (%#"PRIx32") cannot be emulated in protocol %d",
+    if(flags & (uint32_t) ~(SSH_FXF_ACCESS_DISPOSITION | SSH_FXF_APPEND_DATA |
+                            SSH_FXF_APPEND_DATA_ATOMIC | SSH_FXF_TEXT_MODE))
+      return error("future SSH_FXP_OPEN flags (%#" PRIx32
+                   ") cannot be emulated in protocol %d",
                    flags, protocol->version);
     sftp_send_begin(&fakeworker);
     sftp_send_uint8(&fakeworker, SSH_FXP_OPEN);
@@ -827,8 +818,7 @@ struct space_available {
   uint32_t bytes_per_allocation_unit;
 };
 
-static int sftp_space_available(const char *path,
-                                struct space_available *as) {
+static int sftp_space_available(const char *path, struct space_available *as) {
   uint32_t id;
 
   remote_cwd();
@@ -838,8 +828,8 @@ static int sftp_space_available(const char *path,
   sftp_send_string(&fakeworker, "space-available");
   sftp_send_path(&fakejob, &fakeworker, path);
   sftp_send_end(&fakeworker);
-  if(getresponse(SSH_FXP_EXTENDED_REPLY,
-                 id, "space-available") != SSH_FXP_EXTENDED_REPLY)
+  if(getresponse(SSH_FXP_EXTENDED_REPLY, id, "space-available") !=
+     SSH_FXP_EXTENDED_REPLY)
     return -1;
   cpcheck(sftp_parse_uint64(&fakejob, &as->bytes_on_device));
   cpcheck(sftp_parse_uint64(&fakejob, &as->unused_bytes_on_device));
@@ -885,7 +875,7 @@ static char *sftp_readlink(const char *path) {
     return 0;
   cpcheck(sftp_parse_uint32(&fakejob, &u32));
   if(u32 != 1)
-    fatal("wrong count in SSH_FXP_READLINK reply");
+    sftp_fatal("wrong count in SSH_FXP_READLINK reply");
   cpcheck(sftp_parse_path(&fakejob, &resolved));
   return resolved;
 }
@@ -918,8 +908,7 @@ struct statvfs_reply {
   uint64_t namemax;
 };
 
-static int sftp_statvfs(const char *path,
-                        struct statvfs_reply *sr) {
+static int sftp_statvfs(const char *path, struct statvfs_reply *sr) {
   uint32_t id;
 
   remote_cwd();
@@ -932,6 +921,8 @@ static int sftp_statvfs(const char *path,
   sftp_send_path(&fakejob, &fakeworker, path);
   sftp_send_end(&fakeworker);
   getresponse(SSH_FXP_EXTENDED_REPLY, id, statvfs_extension);
+  sftp_memset(sr, 0,
+              sizeof *sr); // workaround overenthusiastic warning with LTO
   cpcheck(sftp_parse_uint64(&fakejob, &sr->bsize));
   cpcheck(sftp_parse_uint64(&fakejob, &sr->frsize));
   cpcheck(sftp_parse_uint64(&fakejob, &sr->blocks));
@@ -948,14 +939,12 @@ static int sftp_statvfs(const char *path,
 
 /* Command line operations */
 
-static int cmd_pwd(int attribute((unused)) ac,
-                   char attribute((unused)) **av) {
-  xprintf("%s\n", remote_cwd());
+static int cmd_pwd(int attribute((unused)) ac, char attribute((unused)) * *av) {
+  sftp_xprintf("%s\n", remote_cwd());
   return 0;
 }
 
-static int cmd_cd(int attribute((unused)) ac,
-                  char **av) {
+static int cmd_cd(int attribute((unused)) ac, char **av) {
   const char *newcwd;
   struct sftpattr attrs;
 
@@ -984,32 +973,30 @@ static int cmd_cd(int attribute((unused)) ac,
     return -1;
   }
   free(cwd);
-  cwd = xstrdup(newcwd);
+  cwd = sftp_xstrdup(newcwd);
   return 0;
 }
 
 static int cmd_quit(int attribute((unused)) ac,
-                    char attribute((unused)) **av) {
+                    char attribute((unused)) * *av) {
   exit(0);
 }
 
-static int cmd_help(int attribute((unused)) ac,
-                    char attribute((unused)) **av);
+static int cmd_help(int attribute((unused)) ac, char attribute((unused)) * *av);
 
 static int cmd_lpwd(int attribute((unused)) ac,
-                    char attribute((unused)) **av) {
+                    char attribute((unused)) * *av) {
   char *lpwd;
 
   if(!(lpwd = sftp_getcwd(fakejob.a))) {
     error("error calling getcwd: %s", strerror(errno));
     return -1;
   }
-  xprintf("%s\n", lpwd);
+  sftp_xprintf("%s\n", lpwd);
   return 0;
 }
 
-static int cmd_lcd(int attribute((unused)) ac,
-                   char **av) {
+static int cmd_lcd(int attribute((unused)) ac, char **av) {
   if(chdir(av[0]) < 0) {
     error("error calling chdir: %s", strerror(errno));
     return -1;
@@ -1056,24 +1043,23 @@ static int sort_by_mtime(const void *av, const void *bv) {
 /* Reverse an array in place */
 static void reverse(void *array, size_t count, size_t size) {
   if(array) {
-    void *tmp = xmalloc(size);
+    void *tmp = sftp_xmalloc(size);
     char *const base = array;
     size_t n;
 
-    /* If size is even then size/2 is the first half of the array and that's fine.
-     * If size is odd then size/2 goes up to but excludes the middle member
-     * which is also fine. */
+    /* If size is even then size/2 is the first half of the array and that's
+     * fine. If size is odd then size/2 goes up to but excludes the middle
+     * member which is also fine. */
     for(n = 0; n < size / 2; ++n) {
-      memcpy(tmp, base + n * size, size);
-      memcpy(base + n * size, base + (count - n - 1) * size, size);
-      memcpy(base + (count - n - 1) * size, tmp, size);
+      sftp_memcpy(tmp, base + n * size, size);
+      sftp_memcpy(base + n * size, base + (count - n - 1) * size, size);
+      sftp_memcpy(base + (count - n - 1) * size, tmp, size);
     }
     free(tmp);
   }
 }
 
-static int cmd_ls(int ac,
-                  char **av) {
+static int cmd_ls(int ac, char **av) {
   const char *options, *path;
   struct sftpattr *attrs, *allattrs = 0, fileattrs;
   size_t nattrs, nallattrs = 0, n, m, i, maxnamewidth = 0;
@@ -1091,8 +1077,7 @@ static int cmd_ls(int ac,
   /* See what type the file is */
   if(sftp_stat(path, &fileattrs, SSH_FXP_LSTAT))
     return -1;
-  if(fileattrs.type != SSH_FILEXFER_TYPE_DIRECTORY
-     || strchr(options, 'd')) {
+  if(fileattrs.type != SSH_FILEXFER_TYPE_DIRECTORY || strchr(options, 'd')) {
     /* The file is not a directory, or we used -d */
     allattrs = &fileattrs;
     nallattrs = 1;
@@ -1111,8 +1096,8 @@ static int cmd_ls(int ac,
         return -1;
       }
       if(!nattrs)
-        break;                          /* eof */
-      allattrs = xrecalloc(allattrs, nattrs + nallattrs, sizeof *attrs);
+        break; /* eof */
+      allattrs = sftp_xrecalloc(allattrs, nattrs + nallattrs, sizeof *attrs);
       for(n = 0; n < nattrs; ++n) {
         if(include_dotfiles || attrs[n].name[0] != '.') {
           wchar_t *wname = sftp_mbs2wcs(attrs[n].name);
@@ -1144,42 +1129,41 @@ static int cmd_ls(int ac,
     /* long listing */
     time_t now;
     struct tm nowtime;
-    const unsigned long flags = (strchr(options, 'n')
-                                 ? FORMAT_PREFER_NUMERIC_UID
-                                 : 0)|FORMAT_PREFER_LOCALTIME|FORMAT_ATTRS;
-    
+    const unsigned long flags =
+        (strchr(options, 'n') ? FORMAT_PREFER_NUMERIC_UID : 0) |
+        FORMAT_PREFER_LOCALTIME | FORMAT_ATTRS;
+
     /* We'd like to know what year we're in for dates in longname */
     time(&now);
     gmtime_r(&now, &nowtime);
     for(n = 0; n < nallattrs; ++n) {
       struct sftpattr *const attrs = &allattrs[n];
-      if(attrs->type == SSH_FILEXFER_TYPE_SYMLINK
-         && !attrs->target) {
+      if(attrs->type == SSH_FILEXFER_TYPE_SYMLINK && !attrs->target) {
         if(singlefile)
           attrs->target = sftp_readlink(attrs->name);
         else {
-          char *const fullname = sftp_alloc(fakejob.a,
-                                            strlen(path) + strlen(attrs->name)
-                                            + 2);
+          char *const fullname =
+              sftp_alloc(fakejob.a, strlen(path) + strlen(attrs->name) + 2);
           strcpy(fullname, path);
           strcat(fullname, "/");
           strcat(fullname, attrs->name);
-          D(("%s -> %s",  attrs->name, fullname));
+          D(("%s -> %s", attrs->name, fullname));
           attrs->target = sftp_readlink(fullname);
         }
       }
-      xprintf("%s\n", sftp_format_attr(fakejob.a, attrs, nowtime.tm_year, flags));
+      sftp_xprintf("%s\n",
+                   sftp_format_attr(fakejob.a, attrs, nowtime.tm_year, flags));
     }
   } else if(strchr(options, '1')) {
     /* single-column listing */
     for(n = 0; n < nallattrs; ++n)
-      xprintf("%s\n", allattrs[n].name);
+      sftp_xprintf("%s\n", allattrs[n].name);
   } else {
     /* multi-column listing.  First figure out the terminal width. */
     /* We have C columns of width M, with C-1 single-character blank columns
      * between them.  So the total width is C * M + (C - 1).  The lot had
      * better fit into W columns in total.
-     * 
+     *
      * We want to find the maximum C such that:
      *     C * M + C - 1 <= W
      * <=> C * (M + 1) <= W + 1
@@ -1216,12 +1200,13 @@ static int cmd_ls(int ac,
         wchar_t *wname = sftp_mbs2wcs(allattrs[i].name);
         const size_t w = wcswidth(wname, SIZE_MAX);
         free(wname);
-        xprintf("%s%*s",
-                allattrs[i].name,
-                (m + 1 < cols && i + rows < nallattrs
-                 ? (int)(maxnamewidth - w + 1) : 0), "");
+        sftp_xprintf("%s%*s", allattrs[i].name,
+                     (m + 1 < cols && i + rows < nallattrs
+                          ? (int)(maxnamewidth - w + 1)
+                          : 0),
+                     "");
       }
-      xprintf("\n");
+      sftp_xprintf("\n");
     }
   }
   if(allattrs != &fileattrs)
@@ -1229,9 +1214,8 @@ static int cmd_ls(int ac,
   return 0;
 }
 
-static int cmd_lls(int ac,
-                   char **av) {
-  const char **args = sftp_alloc(fakejob.a, (ac + 2) * sizeof (char *));
+static int cmd_lls(int ac, char **av) {
+  const char **args = sftp_alloc(fakejob.a, (ac + 2) * sizeof(char *));
   int n = 0;
   pid_t pid;
 
@@ -1239,12 +1223,12 @@ static int cmd_lls(int ac,
   while(ac--)
     args[n++] = *av++;
   args[n] = 0;
-  if(!(pid = xfork())) {
+  if(!(pid = sftp_xfork())) {
     execvp(args[0], (void *)args);
-    fatal("executing ls: %s", strerror(errno));
+    sftp_fatal("executing ls: %s", strerror(errno));
   }
   if(waitpid(pid, &n, 0) < 0) {
-    fatal("error calling waitpid: %s", strerror(errno));
+    sftp_fatal("error calling waitpid: %s", strerror(errno));
     if(n) {
       error("ls returned status %#x", n);
       return -1;
@@ -1253,8 +1237,7 @@ static int cmd_lls(int ac,
   return 0;
 }
 
-static int cmd_lumask(int ac,
-                      char **av) {
+static int cmd_lumask(int ac, char **av) {
   mode_t n;
 
   if(ac) {
@@ -1272,13 +1255,12 @@ static int cmd_lumask(int ac,
   } else {
     n = umask(0);
     umask(n);
-    xprintf("%03o\n", (unsigned)n);
+    sftp_xprintf("%03o\n", (unsigned)n);
   }
   return 0;
 }
 
-static int cmd_lmkdir(int attribute((unused)) ac,
-                      char **av) {
+static int cmd_lmkdir(int attribute((unused)) ac, char **av) {
   if(mkdir(av[0], 0777) < 0) {
     error("creating directory %s: %s", av[0], strerror(errno));
     return -1;
@@ -1286,10 +1268,9 @@ static int cmd_lmkdir(int attribute((unused)) ac,
   return 0;
 }
 
-static int cmd_chown(int attribute((unused)) ac,
-                     char **av) {
+static int cmd_chown(int attribute((unused)) ac, char **av) {
   struct sftpattr attrs;
-  
+
   if(sftp_stat(av[1], &attrs, SSH_FXP_STAT))
     return -1;
   if(protocol->version >= 4) {
@@ -1304,10 +1285,9 @@ static int cmd_chown(int attribute((unused)) ac,
   return sftp_setstat(av[1], &attrs);
 }
 
-static int cmd_chgrp(int attribute((unused)) ac,
-                     char **av) {
+static int cmd_chgrp(int attribute((unused)) ac, char **av) {
   struct sftpattr attrs;
-  
+
   if(sftp_stat(av[1], &attrs, SSH_FXP_STAT))
     return -1;
   if(protocol->version >= 4) {
@@ -1322,10 +1302,9 @@ static int cmd_chgrp(int attribute((unused)) ac,
   return sftp_setstat(av[1], &attrs);
 }
 
-static int cmd_chmod(int attribute((unused)) ac,
-                     char **av) {
+static int cmd_chmod(int attribute((unused)) ac, char **av) {
   struct sftpattr attrs;
-  
+
   attrs.valid = SSH_FILEXFER_ATTR_PERMISSIONS;
   attrs.type = SSH_FILEXFER_TYPE_UNKNOWN;
   errno = 0;
@@ -1335,18 +1314,15 @@ static int cmd_chmod(int attribute((unused)) ac,
   return sftp_setstat(av[1], &attrs);
 }
 
-static int cmd_rm(int attribute((unused)) ac,
-                  char **av) {
+static int cmd_rm(int attribute((unused)) ac, char **av) {
   return sftp_remove(av[0]);
 }
 
-static int cmd_rmdir(int attribute((unused)) ac,
-                     char **av) {
+static int cmd_rmdir(int attribute((unused)) ac, char **av) {
   return sftp_rmdir(av[0]);
 }
 
-static int cmd_mv(int attribute((unused)) ac,
-                     char **av) {
+static int cmd_mv(int attribute((unused)) ac, char **av) {
   if(ac == 3) {
     const char *ptr = av[0];
     int c;
@@ -1357,11 +1333,20 @@ static int cmd_mv(int attribute((unused)) ac,
       return error("invalid options '%s'", av[0]);
     while((c = *ptr++)) {
       switch(c) {
-      case 'n': flags |= SSH_FXF_RENAME_NATIVE; break;
-      case 'a': flags |= SSH_FXF_RENAME_ATOMIC; break;
-      case 'o': flags |= SSH_FXF_RENAME_OVERWRITE; break;
-      case 'p': posixrename = 1; break;
-      default: return error("invalid options '%s'", av[0]);
+      case 'n':
+        flags |= SSH_FXF_RENAME_NATIVE;
+        break;
+      case 'a':
+        flags |= SSH_FXF_RENAME_ATOMIC;
+        break;
+      case 'o':
+        flags |= SSH_FXF_RENAME_OVERWRITE;
+        break;
+      case 'p':
+        posixrename = 1;
+        break;
+      default:
+        return error("invalid options '%s'", av[0]);
       }
     }
     if(posixrename)
@@ -1372,44 +1357,42 @@ static int cmd_mv(int attribute((unused)) ac,
     return sftp_rename(av[0], av[1], 0);
 }
 
-static int cmd_symlink(int attribute((unused)) ac,
-                       char **av) {
+static int cmd_symlink(int attribute((unused)) ac, char **av) {
   return sftp_link(av[0], av[1], 1);
 }
 
-static int cmd_link(int attribute((unused)) ac,
-                    char **av) {
+static int cmd_link(int attribute((unused)) ac, char **av) {
   return sftp_link(av[0], av[1], 0);
 }
 
 /* cmd_get uses a background thread to send requests */
 struct outstanding_read {
-  uint32_t id;                          /* 0 or a request ID */
-  off_t offset;                         /* offset in source file */
+  uint32_t id;  /* 0 or a request ID */
+  off_t offset; /* offset in source file */
 };
 
 struct reader_data {
-  pthread_mutex_t m;                    /* protects everything here */
-  pthread_cond_t c1;                    /* signaled when a response received */
-  pthread_cond_t c2;                    /* signaled when a request sent */
-  struct client_handle h;               /* target handle */
-  struct outstanding_read *reqs;        /* in-flight requests */
-  uint64_t next_offset;                 /* next offset */
+  pthread_mutex_t m;             /* protects everything here */
+  pthread_cond_t c1;             /* signaled when a response received */
+  pthread_cond_t c2;             /* signaled when a request sent */
+  struct client_handle h;        /* target handle */
+  struct outstanding_read *reqs; /* in-flight requests */
+  uint64_t next_offset;          /* next offset */
   int outstanding, eof, failed;
-  uint64_t size;                        /* file size */
-  uint64_t written;                     /* byte written so far */
-  int fd;                               /* file to write to */
-  char *local, *tmp;                    /* output filename */
+  uint64_t size;     /* file size */
+  uint64_t written;  /* byte written so far */
+  int fd;            /* file to write to */
+  char *local, *tmp; /* output filename */
   /* For text translation: */
-  FILE *translated_fp;                  /* file to write to (in stdio-speak) */
-  size_t translated_state;              /* how far thru newline we've seen */
+  FILE *translated_fp;     /* file to write to (in stdio-speak) */
+  size_t translated_state; /* how far thru newline we've seen */
 };
 
 static void *reader_thread(void *arg) {
   struct reader_data *const r = arg;
   int n;
   uint32_t id, len;
-  
+
   ferrcheck(pthread_mutex_lock(&r->m));
   while(!r->eof && !r->failed) {
     /* Wait for a job to be reaped */
@@ -1460,8 +1443,8 @@ static int write_translated_init(struct reader_data *r) {
   return 0;
 }
 
-static int write_translated(struct reader_data *r,
-                            const void *vptr, size_t bytes) {
+static int write_translated(struct reader_data *r, const void *vptr,
+                            size_t bytes) {
   const char *ptr = vptr;
   while(bytes > 0) {
     const int c = (unsigned char)*ptr++;
@@ -1481,8 +1464,8 @@ static int write_translated(struct reader_data *r,
     } else {
       if(r->translated_state) {
         /* We're part way thru something that turned out not to be a newline. */
-        if(fwrite(newline, 1, r->translated_state, r->translated_fp)
-           != r->translated_state)
+        if(fwrite(newline, 1, r->translated_state, r->translated_fp) !=
+           r->translated_state)
           return -1;
         r->translated_state = 0;
         /* Try again from the current point. */
@@ -1507,7 +1490,8 @@ static int write_translated_done(struct reader_data *r) {
     if(r->translated_state) {
       /* The file ends part way thru something that starts out like a newline
        * sequence but turns out not to be one. */
-      if(fwrite(newline, 1, r->translated_state, r->translated_fp) != r->translated_state)
+      if(fwrite(newline, 1, r->translated_state, r->translated_fp) !=
+         r->translated_state)
         rc = -1;
       r->translated_state = 0;
     }
@@ -1556,7 +1540,7 @@ static void reap_write_response(struct reader_data *r) {
      * the right place in the file according to what we asked for.  There's
      * not much point releasing the lock while doing the write - the
      * background thread will have done all it wants while we were awaiting
-     * the response. 
+     * the response.
      *
      * In text mode we can rely on the responses arriving in the correct
      * order.
@@ -1575,12 +1559,11 @@ static void reap_write_response(struct reader_data *r) {
     progress(r->local, r->written, r->size);
     break;
   default:
-    fatal("unexpected response %d to SSH_FXP_READ", rtype);
+    sftp_fatal("unexpected response %d to SSH_FXP_READ", rtype);
   }
 }
 
-static int cmd_get(int ac,
-                   char **av) {
+static int cmd_get(int ac, char **av) {
   int preserve = 0;
   const char *e;
   char *remote;
@@ -1593,8 +1576,8 @@ static int cmd_get(int ac,
   int seek = 0;
   uint64_t line = 0;
 
-  memset(&attrs, 0, sizeof attrs);
-  memset(&r, 0, sizeof r);
+  sftp_memset(&attrs, 0, sizeof attrs);
+  sftp_memset(&r, 0, sizeof r);
   r.fd = -1;
   if(av[0][0] == '-') {
     const char *s = *av++;
@@ -1605,7 +1588,7 @@ static int cmd_get(int ac,
         preserve = 1;
         break;
       case 'f':
-        flags |= SSH_FXF_NOFOLLOW; 
+        flags |= SSH_FXF_NOFOLLOW;
         break;
       case 'L':
         seek = 1;
@@ -1628,7 +1611,7 @@ static int cmd_get(int ac,
   /* we'll write to a temporary file */
   r.tmp = sftp_alloc(fakejob.a, strlen(r.local) + 5);
   sprintf(r.tmp, "%s.new", r.local);
-  if((r.fd = open(r.tmp, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
+  if((r.fd = open(r.tmp, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) {
     error("error opening %s: %s", r.tmp, strerror(errno));
     goto error;
   }
@@ -1639,9 +1622,8 @@ static int cmd_get(int ac,
     r.fd = -1;
   }
   /* open the remote file */
-  if(sftp_open(remote, ACE4_READ_DATA|ACE4_READ_ATTRIBUTES,
-               SSH_FXF_OPEN_EXISTING|flags,
-               &attrs, &r.h))
+  if(sftp_open(remote, ACE4_READ_DATA | ACE4_READ_ATTRIBUTES,
+               SSH_FXF_OPEN_EXISTING | flags, &attrs, &r.h))
     goto error;
   /* stat the file */
   if(sftp_fstat(&r.h, &attrs))
@@ -1649,8 +1631,8 @@ static int cmd_get(int ac,
   if(!textmode && (attrs.valid & SSH_FILEXFER_ATTR_SIZE)) {
     /* We know how big the file is.  Check we can fit it! */
     if((uint64_t)(off_t)attrs.size != attrs.size) {
-      error("remote file %s is too large (%"PRIu64" bytes)",
-            remote, attrs.size);
+      error("remote file %s is too large (%" PRIu64 " bytes)", remote,
+            attrs.size);
       goto error;
     }
     r.size = attrs.size;
@@ -1663,7 +1645,7 @@ static int cmd_get(int ac,
     if(sftp_text_seek(&r.h, line))
       goto error;
   }
-  gettimeofday(&started,  0);
+  gettimeofday(&started, 0);
   ferrcheck(pthread_mutex_init(&r.m, 0));
   ferrcheck(pthread_cond_init(&r.c1, 0));
   ferrcheck(pthread_cond_init(&r.c2, 0));
@@ -1680,7 +1662,7 @@ static int cmd_get(int ac,
     while(!r.outstanding)
       ferrcheck(pthread_cond_wait(&r.c2, &r.m));
     reap_write_response(&r);
-    /* Notify the background thread that something changed. */ 
+    /* Notify the background thread that something changed. */
     ferrcheck(pthread_cond_signal(&r.c1));
   }
   ferrcheck(pthread_mutex_unlock(&r.m));
@@ -1696,23 +1678,23 @@ static int cmd_get(int ac,
   ferrcheck(pthread_cond_destroy(&r.c1));
   ferrcheck(pthread_cond_destroy(&r.c2));
   progress(0, 0, 0);
-  if(r.failed) 
+  if(r.failed)
     goto error;
   gettimeofday(&finished, 0);
   if(progress_indicators) {
-    elapsed = ((finished.tv_sec - started.tv_sec)
-               + (finished.tv_usec - started.tv_usec) / 1000000.0);
-    xprintf("%"PRIu64" bytes in %.1f seconds", r.written, elapsed);
+    elapsed = ((finished.tv_sec - started.tv_sec) +
+               (finished.tv_usec - started.tv_usec) / 1000000.0);
+    sftp_xprintf("%" PRIu64 " bytes in %.1f seconds", r.written, elapsed);
     if(elapsed > 0.1)
-      xprintf(" %.0f bytes/sec", r.written / elapsed);
-    xprintf("\n");
+      sftp_xprintf(" %.0f bytes/sec", r.written / elapsed);
+    sftp_xprintf("\n");
   }
   /* Close the handle */
   sftp_close(&r.h);
   r.h.len = 0;
   if(preserve) {
     /* Set permissions etc */
-    attrs.valid &= ~SSH_FILEXFER_ATTR_SIZE; /* don't truncate */
+    attrs.valid &= ~SSH_FILEXFER_ATTR_SIZE;   /* don't truncate */
     attrs.valid &= ~SSH_FILEXFER_ATTR_UIDGID; /* different mapping! */
     if(sftp_set_fstatus(fakejob.a, r.fd, &attrs, &e) != SSH_FX_OK) {
       error("cannot %s %s: %s", e, r.tmp, strerror(errno));
@@ -1735,7 +1717,7 @@ static int cmd_get(int ac,
   }
   return 0;
 error:
-  write_translated_done(&r);            /* ok to call if not initialized */
+  write_translated_done(&r); /* ok to call if not initialized */
   if(r.fd >= 0)
     close(r.fd);
   if(r.tmp)
@@ -1747,20 +1729,20 @@ error:
 
 /* put uses a thread to gather responses */
 struct outstanding_write {
-  uint32_t id;                          /* or 0 for empty slot */
-  ssize_t n;                            /* size of this request */
+  uint32_t id; /* or 0 for empty slot */
+  ssize_t n;   /* size of this request */
 };
 
 struct writer_data {
-  pthread_mutex_t m;                    /* protects everything here */
-  pthread_cond_t c1;                    /* signal when writer modifies */
-  pthread_cond_t c2;                    /* signal when reader modifies */
-  int failed;                           /* set on failure */
-  int outstanding;                      /* number of outstanding requests */
-  int finished;                         /* set when writer finished */
-  struct outstanding_write *reqs;       /* outstanding requests */
-  const char *remote;                   /* remote path */
-  uint64_t written, total;              /* total size */
+  pthread_mutex_t m;              /* protects everything here */
+  pthread_cond_t c1;              /* signal when writer modifies */
+  pthread_cond_t c2;              /* signal when reader modifies */
+  int failed;                     /* set on failure */
+  int outstanding;                /* number of outstanding requests */
+  int finished;                   /* set when writer finished */
+  struct outstanding_write *reqs; /* outstanding requests */
+  const char *remote;             /* remote path */
+  uint64_t written, total;        /* total size */
 };
 
 static void *writer_thread(void *arg) {
@@ -1778,7 +1760,7 @@ static void *writer_thread(void *arg) {
       continue;
     }
     /* Await the incoming response */
-    getresponse(SSH_FXP_STATUS, 0/*don't care about id*/, "SSH_FXP_WRITE");
+    getresponse(SSH_FXP_STATUS, 0 /*don't care about id*/, "SSH_FXP_WRITE");
     ferrcheck(pthread_cond_signal(&w->c2));
     /* Find the request ID */
     for(i = 0; i < nrequests && w->reqs[i].id != fakejob.id; ++i)
@@ -1796,13 +1778,12 @@ static void *writer_thread(void *arg) {
       w->failed = 1;
     }
   }
-  progress(0, 0, 0);                    /* clear progress indicator */
+  progress(0, 0, 0); /* clear progress indicator */
   ferrcheck(pthread_mutex_unlock(&w->m));
   return 0;
 }
 
-static int cmd_put(int ac,
-                   char **av) {
+static int cmd_put(int ac, char **av) {
   char *local;
   const char *remote;
   struct sftpattr attrs;
@@ -1821,9 +1802,9 @@ static int cmd_put(int ac,
   int setmode = 0;
   mode_t mode = 0;
 
-  memset(&h, 0, sizeof h);
-  memset(&attrs, 0, sizeof attrs);
-  memset(&w, 0, sizeof w);
+  sftp_memset(&h, 0, sizeof h);
+  sftp_memset(&attrs, 0, sizeof attrs);
+  sftp_memset(&w, 0, sizeof w);
   if(av[0][0] == '-') {
     const char *s = *av++;
     ++s;
@@ -1832,16 +1813,16 @@ static int cmd_put(int ac,
       case 'P':
         preserve = 1;
         break;
-      case 'a': 
+      case 'a':
         disp = SSH_FXF_OPEN_OR_CREATE;
-        flags |= SSH_FXF_APPEND_DATA; 
+        flags |= SSH_FXF_APPEND_DATA;
         break;
-      case 'A': 
+      case 'A':
         disp = SSH_FXF_OPEN_EXISTING;
-        flags |= SSH_FXF_APPEND_DATA; 
+        flags |= SSH_FXF_APPEND_DATA;
         break;
       case 'f':
-        flags |= SSH_FXF_NOFOLLOW; 
+        flags |= SSH_FXF_NOFOLLOW;
         break;
       case 't':
         disp = SSH_FXF_CREATE_NEW;
@@ -1870,7 +1851,7 @@ static int cmd_put(int ac,
     --ac;
   } else
     remote = basename(local);
- if((fd = open(local, O_RDONLY)) < 0) {
+  if((fd = open(local, O_RDONLY)) < 0) {
     error("cannot open %s: %s", local, strerror(errno));
     goto error;
   }
@@ -1895,13 +1876,13 @@ static int cmd_put(int ac,
     /* Mask out things that don't make sense: we set the size by dint of
      * uploading data, we don't want to try to set a numeric UID or GID, and we
      * cannot set the allocation size or link count. */
-    attrs.valid &= ~(SSH_FILEXFER_ATTR_SIZE
-                     |SSH_FILEXFER_ATTR_LINK_COUNT
-                     |SSH_FILEXFER_ATTR_UIDGID);
+    attrs.valid &=
+        (uint32_t) ~(SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_LINK_COUNT |
+                     SSH_FILEXFER_ATTR_UIDGID);
     /* Mask off attributes that don't work in this protocol version */
     attrs.valid &= attrmask;
     assert(!(attrs.valid & SSH_FILEXFER_ATTR_CTIME));
-    attrs.attrib_bits &= ~SSH_FILEXFER_ATTR_FLAGS_HIDDEN;
+    attrs.attrib_bits &= (uint32_t)~SSH_FILEXFER_ATTR_FLAGS_HIDDEN;
   }
   if(setmode) {
     attrs.valid |= SSH_FILEXFER_ATTR_PERMISSIONS;
@@ -1909,8 +1890,7 @@ static int cmd_put(int ac,
   }
   if(textmode)
     flags |= SSH_FXF_TEXT_MODE;
-  if(sftp_open(remote, ACE4_WRITE_DATA|ACE4_WRITE_ATTRIBUTES,
-               disp | flags,
+  if(sftp_open(remote, ACE4_WRITE_DATA | ACE4_WRITE_ATTRIBUTES, disp | flags,
                &attrs, &h))
     goto error;
   if(textmode) {
@@ -1922,7 +1902,7 @@ static int cmd_put(int ac,
   }
   w.reqs = sftp_alloc(fakejob.a, nrequests * sizeof *w.reqs);
   w.remote = remote;
-  gettimeofday(&started,  0);
+  gettimeofday(&started, 0);
   ferrcheck(pthread_mutex_init(&w.m, 0));
   ferrcheck(pthread_cond_init(&w.c1, 0));
   ferrcheck(pthread_cond_init(&w.c2, 0));
@@ -1945,15 +1925,15 @@ static int cmd_put(int ac,
     sftp_send_uint64(&fakeworker, offset);
     sftp_send_need(fakejob.worker, buffersize + 4);
     if(textmode) {
-      char *const start = ((char *)fakejob.worker->buffer
-                           + fakejob.worker->bufused + 4);
+      char *const start =
+          ((char *)fakejob.worker->buffer + fakejob.worker->bufused + 4);
       char *ptr = start;
       size_t left = buffersize;
       const size_t newline_len = strlen(newline);
       int c;
       /* We will need to perform a translation step.  We read from stdio into
        * our buffer expanding newlines as necessary. */
-      
+
       while(left > 0 && (c = getc(fp)) != EOF) {
         if(c == '\n') {
           /* We found a newline.  Let us translated it to the desired wire
@@ -1966,7 +1946,7 @@ static int cmd_put(int ac,
           } else {
             /* Whoops, we cannot fit a translated newline in. */
             if(ungetc(c, fp) < 0)
-              fatal("ungetc: %s", strerror(errno));
+              sftp_fatal("ungetc: %s", strerror(errno));
           }
         } else {
           /* This character is not a newline. */
@@ -2025,15 +2005,15 @@ static int cmd_put(int ac,
     goto error;
   gettimeofday(&finished, 0);
   if(progress_indicators) {
-    elapsed = ((finished.tv_sec - started.tv_sec)
-               + (finished.tv_usec - started.tv_usec) / 1000000.0);
-    xprintf("%"PRIu64" bytes in %.1f seconds", w.written, elapsed);
+    elapsed = ((finished.tv_sec - started.tv_sec) +
+               (finished.tv_usec - started.tv_usec) / 1000000.0);
+    sftp_xprintf("%" PRIu64 " bytes in %.1f seconds", w.written, elapsed);
     if(elapsed > 0.1)
-      xprintf(" %.0f bytes/sec", w.written / elapsed);
-    xprintf("\n");
+      sftp_xprintf(" %.0f bytes/sec", w.written / elapsed);
+    sftp_xprintf("\n");
   }
   if(fd >= 0) {
-    close(fd); 
+    close(fd);
     fd = -1;
   }
   if(fp) {
@@ -2054,7 +2034,7 @@ error:
     close(fd);
   if(h.len) {
     sftp_close(&h);
-    sftp_remove(remote);                /* tidy up our mess */
+    sftp_remove(remote); /* tidy up our mess */
   }
   return -1;
 }
@@ -2073,7 +2053,7 @@ static int cmd_progress(int ac, char **av) {
 }
 
 static int cmd_text(int attribute((unused)) ac,
-                    char attribute((unused)) **av) {
+                    char attribute((unused)) * *av) {
   if(protocol->version < 4)
     return error("text mode not supported in protocol version %d",
                  protocol->version);
@@ -2082,13 +2062,12 @@ static int cmd_text(int attribute((unused)) ac,
 }
 
 static int cmd_binary(int attribute((unused)) ac,
-                      char attribute((unused)) **av) {
+                      char attribute((unused)) * *av) {
   textmode = 0;
   return 0;
 }
 
-static int cmd_version(int ac,
-                       char attribute((unused)) **av) {
+static int cmd_version(int ac, char attribute((unused)) * *av) {
   if(ac == 1) {
     const uint32_t id = newid();
 
@@ -2099,29 +2078,35 @@ static int cmd_version(int ac,
     sftp_send_path(&fakejob, &fakeworker, av[0]);
     sftp_send_end(&fakeworker);
     getresponse(SSH_FXP_STATUS, id, "version-select");
-    if(status()) return -1;
-    if(!strcmp(av[0], "3")) protocol = &sftp_v3;
-    else if(!strcmp(av[0], "4")) protocol = &sftp_v4;
-    else if(!strcmp(av[0], "5")) protocol = &sftp_v5;
-    else if(!strcmp(av[0], "6")) protocol = &sftp_v6;
-    else fatal("unknown protocol %s", av[0]);
+    if(status())
+      return -1;
+    if(!strcmp(av[0], "3"))
+      protocol = &sftp_v3;
+    else if(!strcmp(av[0], "4"))
+      protocol = &sftp_v4;
+    else if(!strcmp(av[0], "5"))
+      protocol = &sftp_v5;
+    else if(!strcmp(av[0], "6"))
+      protocol = &sftp_v6;
+    else
+      sftp_fatal("unknown protocol %s", av[0]);
     return 0;
   } else {
-    xprintf("Protocol version: %d\n", protocol->version);
+    sftp_xprintf("Protocol version: %d\n", protocol->version);
     if(servername)
-      xprintf("Server vendor:    %s\n"
-              "Server name:      %s\n"
-              "Server version:   %s\n"
-              "Server build:     %"PRIu64"\n",
-              vendorname, servername, serverversion, serverbuild);
+      sftp_xprintf("Server vendor:    %s\n"
+                   "Server name:      %s\n"
+                   "Server version:   %s\n"
+                   "Server build:     %" PRIu64 "\n",
+                   vendorname, servername, serverversion, serverbuild);
     if(serverversions)
-      xprintf("Server supports:  %s\n", serverversions);
+      sftp_xprintf("Server supports:  %s\n", serverversions);
     return 0;
   }
 }
 
 static int cmd_debug(int attribute((unused)) ac,
-                     char attribute((unused)) **av) {
+                     char attribute((unused)) * *av) {
   sftp_debugging = !sftp_debugging;
   D(("sftp_debugging enabled"));
   return 0;
@@ -2134,34 +2119,32 @@ static void report_bytes(int width, const char *what, uint64_t howmuch) {
 
   if(!howmuch)
     return;
-  xprintf("%s:%*s ", what, width - (int)strlen(what), "");
+  sftp_xprintf("%s:%*s ", what, width - (int)strlen(what), "");
   if(howmuch >= 8 * gbyte)
-    xprintf("%"PRIu64" Gbytes\n", howmuch / gbyte);
+    sftp_xprintf("%" PRIu64 " Gbytes\n", howmuch / gbyte);
   else if(howmuch >= 8 * mbyte)
-    xprintf("%"PRIu64" Mbytes\n", howmuch / mbyte);
+    sftp_xprintf("%" PRIu64 " Mbytes\n", howmuch / mbyte);
   else if(howmuch >= 8 * kbyte)
-    xprintf("%"PRIu64" Kbytes\n", howmuch / kbyte);
-  else 
-    xprintf("%"PRIu64" bytes\n", howmuch);
+    sftp_xprintf("%" PRIu64 " Kbytes\n", howmuch / kbyte);
+  else
+    sftp_xprintf("%" PRIu64 " bytes\n", howmuch);
 }
 
-static int cmd_df(int ac,
-                  char **av) {
+static int cmd_df(int ac, char **av) {
   struct space_available as;
 
-  if(sftp_space_available(ac ? av[0] : remote_cwd(), &as)) 
+  if(sftp_space_available(ac ? av[0] : remote_cwd(), &as))
     return -1;
   report_bytes(32, "Bytes on device", as.bytes_on_device);
   report_bytes(32, "Unused bytes on device", as.unused_bytes_on_device);
   report_bytes(32, "Available bytes on device", as.bytes_available_to_user);
-  report_bytes(32, "Unused available bytes on device", 
+  report_bytes(32, "Unused available bytes on device",
                as.unused_bytes_available_to_user);
   report_bytes(32, "Bytes per allocation unit", as.bytes_per_allocation_unit);
   return 0;
 }
 
-static int cmd_mkdir(int ac,
-                     char **av) {
+static int cmd_mkdir(int ac, char **av) {
   const char *path;
   mode_t mode;
 
@@ -2169,22 +2152,22 @@ static int cmd_mkdir(int ac,
     mode = strtoul(av[0], 0, 8);
     path = av[1];
   } else {
-    mode = -1;
+    mode = (mode_t)-1;
     path = av[0];
   }
   return sftp_mkdir(path, mode);
 }
 
 static int cmd_init(int attribute((unused)) ac,
-                    char attribute((unused)) **av) {
+                    char attribute((unused)) * *av) {
   return sftp_init();
 }
 
 static int cmd_unsupported(int attribute((unused)) ac,
-                           char attribute((unused)) **av) {
+                           char attribute((unused)) * *av) {
   sftp_send_begin(&fakeworker);
-  sftp_send_uint8(&fakeworker, 0xFFFFFFFF);
-  sftp_send_uint32(&fakeworker, 0);          /* id */
+  sftp_send_uint8(&fakeworker, 0xFF);
+  sftp_send_uint32(&fakeworker, 0); /* id */
   sftp_send_end(&fakeworker);
   getresponse(SSH_FXP_STATUS, 0, "_unsupported");
   status();
@@ -2192,10 +2175,10 @@ static int cmd_unsupported(int attribute((unused)) ac,
 }
 
 static int cmd_ext_unsupported(int attribute((unused)) ac,
-                               char attribute((unused)) **av) {
+                               char attribute((unused)) * *av) {
   sftp_send_begin(&fakeworker);
   sftp_send_uint8(&fakeworker, SSH_FXP_EXTENDED);
-  sftp_send_uint32(&fakeworker, 0);          /* id */
+  sftp_send_uint32(&fakeworker, 0); /* id */
   sftp_send_string(&fakeworker, "no-such-sftp-extension@rjk.greenend.org.uk");
   sftp_send_end(&fakeworker);
   getresponse(SSH_FXP_STATUS, 0, "_unsupported");
@@ -2203,30 +2186,27 @@ static int cmd_ext_unsupported(int attribute((unused)) ac,
   return 0;
 }
 
-static int cmd_readlink(int attribute((unused)) ac,
-                        char **av) {
+static int cmd_readlink(int attribute((unused)) ac, char **av) {
   char *r = sftp_readlink(av[0]);
 
   if(r) {
-    xprintf("%s\n", r);
+    sftp_xprintf("%s\n", r);
     return 0;
   } else
     return -1;
 }
 
-static int cmd_realpath(int attribute((unused)) ac,
-                        char **av) {
+static int cmd_realpath(int attribute((unused)) ac, char **av) {
   char *r = sftp_realpath(av[0]);
 
   if(r) {
-    xprintf("%s\n", r);
+    sftp_xprintf("%s\n", r);
     return 0;
   } else
     return -1;
 }
 
-static int cmd_realpath6(int attribute((unused)) ac,
-                         char **av) {
+static int cmd_realpath6(int attribute((unused)) ac, char **av) {
   int control_byte;
   char *resolved;
   struct sftpattr attrs;
@@ -2248,14 +2228,14 @@ static int cmd_realpath6(int attribute((unused)) ac,
     attrs.name = resolved;
     time(&now);
     gmtime_r(&now, &nowtime);
-    xprintf("%s\n", sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
+    sftp_xprintf("%s\n",
+                 sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
   } else
-    xprintf("%s\n", resolved);
+    sftp_xprintf("%s\n", resolved);
   return 0;
 }
 
-static int cmd_lrealpath(int attribute((unused)) ac,
-                         char **av) {
+static int cmd_lrealpath(int attribute((unused)) ac, char **av) {
   char *r;
   unsigned flags;
 
@@ -2264,12 +2244,12 @@ static int cmd_lrealpath(int attribute((unused)) ac,
   else if(!strcmp(av[0], "stat-if"))
     flags = RP_READLINK;
   else if(!strcmp(av[0], "stat-always"))
-    flags = RP_READLINK|RP_MUST_EXIST;
+    flags = RP_READLINK | RP_MUST_EXIST;
   else
     return error("unknown control string '%s'", av[0]);
   r = sftp_find_realpath(fakejob.a, av[1], flags);
   if(r) {
-    xprintf("%s\n", r);
+    sftp_xprintf("%s\n", r);
     return 0;
   } else {
     perror(0);
@@ -2278,7 +2258,7 @@ static int cmd_lrealpath(int attribute((unused)) ac,
 }
 
 static int cmd_bad_handle(int attribute((unused)) ac,
-                          char attribute((unused)) **av) {
+                          char attribute((unused)) * *av) {
   struct client_handle h;
 
   h.len = 8;
@@ -2298,7 +2278,7 @@ static int cmd_bad_handle(int attribute((unused)) ac,
 }
 
 static int cmd_bad_packet(int attribute((unused)) ac,
-                          char attribute((unused)) **av) {
+                          char attribute((unused)) * *av) {
   sftp_send_begin(&fakeworker);
   sftp_send_uint8(&fakeworker, SSH_FXP_READ);
   /* completely missing ID */
@@ -2307,21 +2287,21 @@ static int cmd_bad_packet(int attribute((unused)) ac,
   status();
   sftp_send_begin(&fakeworker);
   sftp_send_uint8(&fakeworker, SSH_FXP_READ);
-  sftp_send_uint8(&fakeworker, 0);           /* broken ID */
+  sftp_send_uint8(&fakeworker, 0); /* broken ID */
   sftp_send_end(&fakeworker);
   getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
   status();
   sftp_send_begin(&fakeworker);
   sftp_send_uint8(&fakeworker, SSH_FXP_READ);
   sftp_send_uint32(&fakeworker, 0);
-  sftp_send_uint8(&fakeworker, 0);           /* truncated handle length */
+  sftp_send_uint8(&fakeworker, 0); /* truncated handle length */
   sftp_send_end(&fakeworker);
   getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
   status();
   sftp_send_begin(&fakeworker);
   sftp_send_uint8(&fakeworker, SSH_FXP_READ);
   sftp_send_uint32(&fakeworker, 0);
-  sftp_send_uint32(&fakeworker, 64);         /* truncated handle */
+  sftp_send_uint32(&fakeworker, 64); /* truncated handle */
   sftp_send_end(&fakeworker);
   getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
   status();
@@ -2336,7 +2316,7 @@ static int cmd_bad_packet(int attribute((unused)) ac,
   sftp_send_uint8(&fakeworker, SSH_FXP_READ);
   sftp_send_uint32(&fakeworker, 0);
   sftp_send_string(&fakeworker, "12345678");
-  sftp_send_uint32(&fakeworker, 0);          /* truncated uint64 */
+  sftp_send_uint32(&fakeworker, 0); /* truncated uint64 */
   sftp_send_end(&fakeworker);
   getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
   status();
@@ -2350,14 +2330,14 @@ static int cmd_bad_packet(int attribute((unused)) ac,
   sftp_send_begin(&fakeworker);
   sftp_send_uint8(&fakeworker, SSH_FXP_READLINK);
   sftp_send_uint32(&fakeworker, 0);
-  sftp_send_uint32(&fakeworker, 32);         /* truncated string */
+  sftp_send_uint32(&fakeworker, 32); /* truncated string */
   sftp_send_end(&fakeworker);
   getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
   status();
   sftp_send_begin(&fakeworker);
   sftp_send_uint8(&fakeworker, SSH_FXP_READLINK);
   sftp_send_uint32(&fakeworker, 0);
-  sftp_send_uint8(&fakeworker, 0);           /* truncated string length */
+  sftp_send_uint8(&fakeworker, 0); /* truncated string length */
   sftp_send_end(&fakeworker);
   getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
   status();
@@ -2365,12 +2345,12 @@ static int cmd_bad_packet(int attribute((unused)) ac,
 }
 
 static int cmd_bad_packet456(int attribute((unused)) ac,
-                             char attribute((unused)) **av) {
+                             char attribute((unused)) * *av) {
   sftp_send_begin(&fakeworker);
   sftp_send_uint8(&fakeworker, SSH_FXP_SETSTAT);
   sftp_send_uint32(&fakeworker, 0);
   sftp_send_string(&fakeworker, "path");
-  sftp_send_uint32(&fakeworker, 0);          /* valid attributes */
+  sftp_send_uint32(&fakeworker, 0); /* valid attributes */
   /* missing type field */
   sftp_send_end(&fakeworker);
   getresponse(SSH_FXP_STATUS, 0, "_bad_packet");
@@ -2379,12 +2359,12 @@ static int cmd_bad_packet456(int attribute((unused)) ac,
 }
 
 static int cmd_bad_path(int attribute((unused)) ac,
-                             char attribute((unused)) **av) {
+                        char attribute((unused)) * *av) {
   sftp_send_begin(&fakeworker);
   sftp_send_uint8(&fakeworker, SSH_FXP_OPENDIR);
   sftp_send_uint32(&fakeworker, 0);
-  sftp_send_string(&fakeworker, "\xC0");     /* can't be the start of a UTF-8
-                                         * sequence */
+  sftp_send_string(&fakeworker, "\xC0"); /* can't be the start of a UTF-8
+                                          * sequence */
   /* missing type field */
   sftp_send_end(&fakeworker);
   getresponse(SSH_FXP_STATUS, 0, "_bad_path");
@@ -2392,75 +2372,77 @@ static int cmd_bad_path(int attribute((unused)) ac,
   return 0;
 }
 
-static int cmd_stat(int attribute((unused)) ac,
-                    char **av) {
+static int cmd_stat(int attribute((unused)) ac, char **av) {
   struct sftpattr attrs;
   time_t now;
   struct tm nowtime;
 
-  if(sftp_stat(av[0], &attrs, SSH_FXP_STAT)) return -1;
+  if(sftp_stat(av[0], &attrs, SSH_FXP_STAT))
+    return -1;
   time(&now);
   gmtime_r(&now, &nowtime);
-  xprintf("%s\n", sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
+  sftp_xprintf("%s\n", sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
   return 0;
 }
 
-static int cmd_lstat(int attribute((unused)) ac,
-                     char **av) {
+static int cmd_lstat(int attribute((unused)) ac, char **av) {
   struct sftpattr attrs;
   time_t now;
   struct tm nowtime;
 
-  if(sftp_stat(av[0], &attrs, SSH_FXP_LSTAT)) return -1;
+  if(sftp_stat(av[0], &attrs, SSH_FXP_LSTAT))
+    return -1;
   time(&now);
   gmtime_r(&now, &nowtime);
-  xprintf("%s\n", sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
+  sftp_xprintf("%s\n", sftp_format_attr(fakejob.a, &attrs, nowtime.tm_year, 0));
   return 0;
 }
 
-static int cmd_statfs(int attribute((unused)) ac,
-                      char **av) {
+static int cmd_statfs(int attribute((unused)) ac, char **av) {
   struct statvfs_reply sr;
 
-  if(sftp_statvfs(av[0], &sr)) return -1;
-  xprintf("bsize %"PRIu64" frsize %"PRIu64
-          " id %"PRIx64" flags %"PRIx64" namemax %"PRIu64"\n"
-          "  blocks %9"PRIu64"/%-9"PRIu64" (%"PRIu64")\n"
-          "  files  %9"PRIu64"/%-9"PRIu64" (%"PRIu64")\n",
-          sr.bsize, sr.frsize,
-          sr.fsid, sr.flags, sr.namemax,
-          sr.bfree, sr.blocks, sr.bavail,
-          sr.ffree, sr.files, sr.favail);
+  if(sftp_statvfs(av[0], &sr))
+    return -1;
+  sftp_xprintf("bsize %" PRIu64 " frsize %" PRIu64 " id %" PRIx64
+               " flags %" PRIx64 " namemax %" PRIu64 "\n"
+               "  blocks %9" PRIu64 "/%-9" PRIu64 " (%" PRIu64 ")\n"
+               "  files  %9" PRIu64 "/%-9" PRIu64 " (%" PRIu64 ")\n",
+               sr.bsize, sr.frsize, sr.fsid, sr.flags, sr.namemax, sr.bfree,
+               sr.blocks, sr.bavail, sr.ffree, sr.files, sr.favail);
   return 0;
 }
 
-static int cmd_truncate(int attribute((unused)) ac,
-                        char **av) {
+static int cmd_truncate(int attribute((unused)) ac, char **av) {
   struct sftpattr attrs;
 
-  memset(&attrs, 0, sizeof attrs);
+  sftp_memset(&attrs, 0, sizeof attrs);
   attrs.valid = SSH_FILEXFER_ATTR_SIZE;
   attrs.size = strtoull(av[0], 0, 0);
   return sftp_setstat(av[1], &attrs);
 }
 
 static int cmd_overlap(int attribute((unused)) ac,
-                       char attribute((unused)) **av) {
+                       char attribute((unused)) * *av) {
   struct sftpattr attrs;
-  static const char a[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
-  static const char b[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
-  static const char c[] = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";
-  static const char d[] = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
-  static const char expect[] = "aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
+  static const char a[] =
+      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+  static const char b[] =
+      "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
+  static const char c[] =
+      "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";
+  static const char d[] =
+      "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
+  static const char expect[] =
+      "aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccdddddddddddddddddddddddd"
+      "dddddddddddddddddddddddddddddddddddddddd";
   char buffer[128];
   int n, r, rc = -1;
   uint32_t ida, idb, idc, idd;
   int fd = -1;
   struct client_handle h;
 
-  memset(&attrs, 0, sizeof attrs);
-  if(sftp_open("dest", ACE4_WRITE_DATA,
-               SSH_FXF_CREATE_TRUNCATE, &attrs, &h))
+  sftp_memset(&attrs, 0, sizeof attrs);
+  if(sftp_open("dest", ACE4_WRITE_DATA, SSH_FXF_CREATE_TRUNCATE, &attrs, &h))
     goto error;
   if((fd = open("dest", O_RDWR)) < 0) {
     perror("open dest");
@@ -2474,7 +2456,7 @@ static int cmd_overlap(int attribute((unused)) ac,
     sftp_send_uint64(&fakeworker, 0);
     sftp_send_bytes(&fakeworker, a, 64);
     sftp_send_end(&fakeworker);
-    
+
     sftp_send_begin(&fakeworker);
     sftp_send_uint8(&fakeworker, SSH_FXP_WRITE);
     sftp_send_uint32(&fakeworker, idb = newid());
@@ -2482,7 +2464,7 @@ static int cmd_overlap(int attribute((unused)) ac,
     sftp_send_uint64(&fakeworker, 16);
     sftp_send_bytes(&fakeworker, b, 64);
     sftp_send_end(&fakeworker);
-    
+
     sftp_send_begin(&fakeworker);
     sftp_send_uint8(&fakeworker, SSH_FXP_WRITE);
     sftp_send_uint32(&fakeworker, idc = newid());
@@ -2490,7 +2472,7 @@ static int cmd_overlap(int attribute((unused)) ac,
     sftp_send_uint64(&fakeworker, 32);
     sftp_send_bytes(&fakeworker, c, 64);
     sftp_send_end(&fakeworker);
-    
+
     sftp_send_begin(&fakeworker);
     sftp_send_uint8(&fakeworker, SSH_FXP_WRITE);
     sftp_send_uint32(&fakeworker, idd = newid());
@@ -2510,13 +2492,14 @@ static int cmd_overlap(int attribute((unused)) ac,
       goto error;
     }
     r = read(fd, buffer, sizeof buffer);
-    if(r != 48+64) {
-      fprintf(stderr, "expected %d bytes got %d\n", 48+64, r);
+    if(r != 48 + 64) {
+      fprintf(stderr, "expected %d bytes got %d\n", 48 + 64, r);
       goto error;
     }
-    buffer[r] = 0;                      /* ensure buffer terminated */
-    if(memcmp(buffer, expect, 48+64)) {
-      fprintf(stderr, "buffer contents mismatch\n"
+    buffer[r] = 0; /* ensure buffer terminated */
+    if(memcmp(buffer, expect, 48 + 64)) {
+      fprintf(stderr,
+              "buffer contents mismatch\n"
               "expect: %s\n"
               "   got: %s\n",
               expect, buffer);
@@ -2534,243 +2517,66 @@ error:
   return rc;
 }
 
-
 /* Table of command line operations */
 static const struct command commands[] = {
-  {
-    "_bad_handle", 0, 0, cmd_bad_handle,
-    0,
-    "operate on a bogus handle"
-  },
-  {
-    "_bad_packet", 0, 0, cmd_bad_packet,
-    0,
-    "send bad packets"
-  },
-  {
-    "_bad_packet456", 0, 0, cmd_bad_packet456,
-    0,
-    "send bad packets (protos >= 4 only)"
-  },
-  {
-    "_bad_path", 0, 0, cmd_bad_path,
-    0,
-    "send bad paths"
-  },
-  {
-    "_ext_unsupported", 0, 0, cmd_ext_unsupported,
-    0,
-    "send an unsupported extension"
-  },
-  {
-    "_init", 0, 0, cmd_init,
-    0,
-    "resend SSH_FXP_INIT"
-  },
-  {
-    "_lrealpath", 2, 2, cmd_lrealpath,
-    "CONTROL PATH",
-    "expand a local path name"
-  },
-  {
-    "_overlap", 0, 0, cmd_overlap,
-    "",
-    "test overlapping writes"
-  },
-  {
-    "_unsupported", 0, 0, cmd_unsupported,
-    0,
-    "send an unsupported command"
-  },
-  {
-    "binary", 0, 0, cmd_binary,
-    0,
-    "binary mode"
-  },
-  {
-    "bye", 0, 0, cmd_quit,
-    0,
-    "quit"
-  },
-  {
-    "cd", 1, 1, cmd_cd,
-    "DIR",
-    "change remote directory"
-  },
-  {
-    "chgrp", 2, 2, cmd_chgrp,
-    "GID PATH",
-    "change remote file group"
-  },
-  {
-    "chmod", 2, 2, cmd_chmod,
-    "OCTAL PATH",
-    "change remote file permissions"
-  },
-  {
-    "chown", 2, 2, cmd_chown,
-    "UID PATH",
-    "change remote file ownership"
-  },
-  {
-    "debug", 0, 0, cmd_debug,
-    0,
-    "toggle sftp_debugging"
-  },
-  {
-    "df", 0, 1, cmd_df,
-    "[PATH]",
-    "query available space"
-  },
-  {
-    "exit", 0, 0, cmd_quit,
-    0,
-    "quit"
-  },
-  {
-    "get", 1, 3, cmd_get,
-    "[-PfL<line>] REMOTE-PATH [LOCAL-PATH]",
-    "retrieve a remote file"
-  },
-  {
-    "help", 0, 0, cmd_help,
-    0,
-    "display help"
-  },
-  {
-    "lcd", 1, 1, cmd_lcd,
-    "DIR",
-    "change local directory"
-  },
-  {
-    "link", 2, 2, cmd_link,
-    "OLDPATH NEWPATH",
-    "create a remote hard link"
-  },
-  {
-    "lpwd", 0, 0, cmd_lpwd,
-    "DIR",
-    "display current local directory"
-  },
-  {
-    "lls", 0, INT_MAX, cmd_lls,
-    "[OPTIONS] [LOCAL-PATH]",
-    "list local directory"
-  },
-  {
-    "lmkdir", 1, 1, cmd_lmkdir,
-    "LOCAL-PATH",
-    "create local directory"
-  },
-  {
-    "ls", 0, 2, cmd_ls,
-    "[OPTIONS] [PATH]",
-    "list remote directory"
-  },
-  {
-    "lstat", 1, 1, cmd_lstat,
-    "PATH",
-    "lstat a file"
-  },
-  {
-    "lumask", 0, 1, cmd_lumask,
-    "OCTAL",
-    "get or set local umask"
-  },
-  {
-    "mkdir", 1, 2, cmd_mkdir,
-    "[MODE] DIRECTORY",
-    "create a remote directory"
-  },
-  {
-    "mv", 2, 3, cmd_mv,
-    "[-naop] OLDPATH NEWPATH",
-    "rename a remote file"
-  },
-  {
-    "progress", 0, 1, cmd_progress,
-    "[on|off]",
-    "set or toggle progress indicators"
-  },
-  {
-    "put", 1, 3, cmd_put, "[-PaftemMODE] LOCAL-PATH [REMOTE-PATH]",
-    "upload a file"
-  },
-  {
-    "pwd", 0, 0, cmd_pwd,
-    0,
-    "display current remote directory" 
-  },
-  {
-    "quit", 0, 0, cmd_quit,
-    0,
-    "quit"
-  },
-  {
-    "readlink", 1, 1, cmd_readlink,
-    "PATH",
-    "inspect a symlink"
-  },
-  {
-    "realpath", 1, 1, cmd_realpath,
-    "PATH",
-    "expand a path name"
-  },
-  {
-    "realpath6", 2, INT_MAX, cmd_realpath6,
-    "CONTROL PATH [COMPOSE...]",
-    "expand a path name"
-  },
-  {
-    "rename", 2, 2, cmd_mv,
-    "OLDPATH NEWPATH",
-    "rename a remote file"
-  },
-  {
-    "rm", 1, 1, cmd_rm,
-    "PATH",
-    "remove remote file"
-  },
-  {
-    "rmdir", 1, 1, cmd_rmdir,
-    "PATH",
-    "remove remote directory"
-  },
-  {
-    "symlink", 2, 2, cmd_symlink,
-    "TARGET NEWPATH",
-    "create a remote symlink"
-  },
-  {
-    "stat", 1, 1, cmd_stat,
-    "PATH",
-    "stat a file"
-  },
-  {
-    "statfs", 1, 1, cmd_statfs,
-    "PATH",
-    "stat a filesystem"
-  },
-  {
-    "text", 0, 0, cmd_text,
-    0,
-    "text mode"
-  },
-  {
-    "truncate", 2, 2, cmd_truncate,
-    "LENGTH FILE",
-    "truncate a file"
-  },
-  {
-    "version", 0, 1, cmd_version,
-    0,
-    "set or display protocol version"
-  },
-  { 0, 0, 0, 0, 0, 0 }
-};
+    {"_bad_handle", 0, 0, cmd_bad_handle, 0, "operate on a bogus handle"},
+    {"_bad_packet", 0, 0, cmd_bad_packet, 0, "send bad packets"},
+    {"_bad_packet456", 0, 0, cmd_bad_packet456, 0,
+     "send bad packets (protos >= 4 only)"},
+    {"_bad_path", 0, 0, cmd_bad_path, 0, "send bad paths"},
+    {"_ext_unsupported", 0, 0, cmd_ext_unsupported, 0,
+     "send an unsupported extension"},
+    {"_init", 0, 0, cmd_init, 0, "resend SSH_FXP_INIT"},
+    {"_lrealpath", 2, 2, cmd_lrealpath, "CONTROL PATH",
+     "expand a local path name"},
+    {"_overlap", 0, 0, cmd_overlap, "", "test overlapping writes"},
+    {"_unsupported", 0, 0, cmd_unsupported, 0, "send an unsupported command"},
+    {"binary", 0, 0, cmd_binary, 0, "binary mode"},
+    {"bye", 0, 0, cmd_quit, 0, "quit"},
+    {"cd", 1, 1, cmd_cd, "DIR", "change remote directory"},
+    {"chgrp", 2, 2, cmd_chgrp, "GID PATH", "change remote file group"},
+    {"chmod", 2, 2, cmd_chmod, "OCTAL PATH", "change remote file permissions"},
+    {"chown", 2, 2, cmd_chown, "UID PATH", "change remote file ownership"},
+    {"debug", 0, 0, cmd_debug, 0, "toggle sftp_debugging"},
+    {"df", 0, 1, cmd_df, "[PATH]", "query available space"},
+    {"exit", 0, 0, cmd_quit, 0, "quit"},
+    {"get", 1, 3, cmd_get, "[-PfL<line>] REMOTE-PATH [LOCAL-PATH]",
+     "retrieve a remote file"},
+    {"help", 0, 0, cmd_help, 0, "display help"},
+    {"lcd", 1, 1, cmd_lcd, "DIR", "change local directory"},
+    {"link", 2, 2, cmd_link, "OLDPATH NEWPATH", "create a remote hard link"},
+    {"lpwd", 0, 0, cmd_lpwd, "DIR", "display current local directory"},
+    {"lls", 0, INT_MAX, cmd_lls, "[OPTIONS] [LOCAL-PATH]",
+     "list local directory"},
+    {"lmkdir", 1, 1, cmd_lmkdir, "LOCAL-PATH", "create local directory"},
+    {"ls", 0, 2, cmd_ls, "[OPTIONS] [PATH]", "list remote directory"},
+    {"lstat", 1, 1, cmd_lstat, "PATH", "lstat a file"},
+    {"lumask", 0, 1, cmd_lumask, "OCTAL", "get or set local umask"},
+    {"mkdir", 1, 2, cmd_mkdir, "[MODE] DIRECTORY", "create a remote directory"},
+    {"mv", 2, 3, cmd_mv, "[-naop] OLDPATH NEWPATH", "rename a remote file"},
+    {"progress", 0, 1, cmd_progress, "[on|off]",
+     "set or toggle progress indicators"},
+    {"put", 1, 3, cmd_put, "[-PaftemMODE] LOCAL-PATH [REMOTE-PATH]",
+     "upload a file"},
+    {"pwd", 0, 0, cmd_pwd, 0, "display current remote directory"},
+    {"quit", 0, 0, cmd_quit, 0, "quit"},
+    {"readlink", 1, 1, cmd_readlink, "PATH", "inspect a symlink"},
+    {"realpath", 1, 1, cmd_realpath, "PATH", "expand a path name"},
+    {"realpath6", 2, INT_MAX, cmd_realpath6, "CONTROL PATH [COMPOSE...]",
+     "expand a path name"},
+    {"rename", 2, 2, cmd_mv, "OLDPATH NEWPATH", "rename a remote file"},
+    {"rm", 1, 1, cmd_rm, "PATH", "remove remote file"},
+    {"rmdir", 1, 1, cmd_rmdir, "PATH", "remove remote directory"},
+    {"symlink", 2, 2, cmd_symlink, "TARGET NEWPATH", "create a remote symlink"},
+    {"stat", 1, 1, cmd_stat, "PATH", "stat a file"},
+    {"statfs", 1, 1, cmd_statfs, "PATH", "stat a filesystem"},
+    {"text", 0, 0, cmd_text, 0, "text mode"},
+    {"truncate", 2, 2, cmd_truncate, "LENGTH FILE", "truncate a file"},
+    {"version", 0, 1, cmd_version, 0, "set or display protocol version"},
+    {0, 0, 0, 0, 0, 0}};
 
 static int cmd_help(int attribute((unused)) ac,
-                    char attribute((unused)) **av) {
+                    char attribute((unused)) * *av) {
   int n;
   size_t max = 0, len = 0;
 
@@ -2780,19 +2586,19 @@ static int cmd_help(int attribute((unused)) ac,
     len = strlen(commands[n].name);
     if(commands[n].args)
       len += strlen(commands[n].args) + 1;
-    if(len > max) 
+    if(len > max)
       max = len;
   }
   for(n = 0; commands[n].name; ++n) {
     if(commands[n].name[0] == '_')
       continue;
     len = strlen(commands[n].name);
-    xprintf("%s", commands[n].name);
+    sftp_xprintf("%s", commands[n].name);
     if(commands[n].args) {
       len += strlen(commands[n].args) + 1;
-      xprintf(" %s", commands[n].args);
+      sftp_xprintf(" %s", commands[n].args);
     }
-    xprintf("%*s  %s\n", (int)(max - len), "", commands[n].help);
+    sftp_xprintf("%*s  %s\n", (int)(max - len), "", commands[n].help);
   }
   return 0;
 }
@@ -2814,14 +2620,14 @@ static char *input(const char *prompt, FILE *fp) {
     }
     return s;
 #else
-    xprintf("%s", prompt);
+    sftp_xprintf("%s", prompt);
     if(fflush(stdout) < 0)
-      fatal("error calling fflush: %s", strerror(errno));
+      sftp_fatal("error calling fflush: %s", strerror(errno));
 #endif
   }
   if(!fgets(buffer, sizeof buffer, fp))
     return 0;
-  return xstrdup(buffer);
+  return sftp_xstrdup(buffer);
 }
 
 /* Input processing loop */
@@ -2829,15 +2635,15 @@ static void process(const char *prompt, FILE *fp) {
   char *line;
   int ac, n, rc;
   char *avbuf[256], **av;
- 
+
   while((line = input(prompt, fp))) {
     ++inputline;
     if(line[0] == '#')
       goto next;
     if(echo) {
-      xprintf("%s", line);
+      sftp_xprintf("%s", line);
       if(fflush(stdout) < 0)
-        fatal("error calling fflush: %s", strerror(errno));
+        sftp_fatal("error calling fflush: %s", strerror(errno));
     }
     if(line[0] == '!') {
       if(line[1] != '\n')
@@ -2850,7 +2656,7 @@ static void process(const char *prompt, FILE *fp) {
     }
     if((ac = split(line, av = avbuf)) < 0) {
       if(stoponerror)
-        fatal("stopping on error");
+        sftp_fatal("stopping on error");
       goto next;
     }
     if(!ac)
@@ -2860,30 +2666,30 @@ static void process(const char *prompt, FILE *fp) {
     if(!commands[n].name) {
       error("unknown command: '%s'", av[0]);
       if(stoponerror)
-        fatal("stopping on error");
+        sftp_fatal("stopping on error");
       goto next;
     }
     ++av;
     --ac;
     if(ac < commands[n].minargs || ac > commands[n].maxargs) {
-      error("wrong number of arguments (got %d, want %d-%d)",
-            ac, commands[n].minargs, commands[n].maxargs);
+      error("wrong number of arguments (got %d, want %d-%d)", ac,
+            commands[n].minargs, commands[n].maxargs);
       if(stoponerror)
-        fatal("stopping on error");
+        sftp_fatal("stopping on error");
       goto next;
     }
     if(commands[n].handler(ac, av) && stoponerror)
-      fatal("stopping on error");
-next:
+      sftp_fatal("stopping on error");
+  next:
     if(fflush(stdout) < 0)
-      fatal("error calling fflush: %s", strerror(errno));
+      sftp_fatal("error calling fflush: %s", strerror(errno));
     sftp_alloc_destroy(fakejob.a);
     free(line);
   }
   if(ferror(fp))
-    fatal("error reading %s: %s", inputpath, strerror(errno));
+    sftp_fatal("error reading %s: %s", inputpath, strerror(errno));
   if(prompt)
-    xprintf("\n");
+    sftp_xprintf("\n");
 }
 
 int main(int argc, char **argv) {
@@ -2895,14 +2701,14 @@ int main(int argc, char **argv) {
   int dropbear = 0;
 
 #if HAVE_GETADDRINFO
-  memset(&hints, 0, sizeof hints);
+  sftp_memset(&hints, 0, sizeof hints);
   hints.ai_flags = 0;
   hints.ai_family = PF_UNSPEC;
   hints.ai_socktype = SOCK_STREAM;
 #endif
 
   setlocale(LC_ALL, "");
-  newline = xstrdup("\r\n");
+  newline = sftp_xstrdup("\r\n");
 
   /* Figure out terminal width */
   {
@@ -2918,41 +2724,104 @@ int main(int argc, char **argv) {
   }
 
   while((n = getopt_long(argc, argv, "hVrB:b:P:R:s:S:12CF:o:vdH:p:46D:",
-			 options, 0)) >= 0) {
+                         options, 0)) >= 0) {
     switch(n) {
-    case 'h': help();
-    case 'V': version();
-    case 'r': dropbear++; break;
-    case 'B': buffersize = atoi(optarg); break;
-    case 'b': batchfile = optarg; stoponerror = 1; progress_indicators = 0; break;
-    case 'P': program = optarg; break;
-    case 'R': nrequests = atoi(optarg); break;
-    case 's': subsystem = optarg; break;
-    case 'S': sftpversion = atoi(optarg); break;
-    case '1': sshversion = 1; break;
-    case '2': sshversion = 2; break;
-    case 'C': compress = 1; break;
-    case 'F': sshconf = optarg; break;
-    case 'o': sshoptions[nsshoptions++] = optarg; break;
-    case 'v': sshverbose++; break;
-    case 'd': sftp_debugging = 1; break;
-    case 'D': sftp_debugging = 1; sftp_debugpath = optarg; break;
-    case 256: quirk_reverse_symlink = 1; break;
-    case 257: stoponerror = 1; break;
-    case 258: stoponerror = 0; break;
-    case 259: progress_indicators = 1; break;
-    case 260: progress_indicators = 0; break;
-    case 261: echo = 1; break;
-    case 262: signal(SIGPIPE, SIG_DFL); break; /* stupid python */
-    case 263: sftpversion = atoi(optarg); forceversion = 1; break;
-    case 264: program_debugpath = optarg; break;
-    case 'H': host = optarg; break;
-    case 'p': port = optarg; break;
+    case 'h':
+      help();
+    case 'V':
+      version();
+    case 'r':
+      dropbear++;
+      break;
+    case 'B':
+      buffersize = atoi(optarg);
+      break;
+    case 'b':
+      batchfile = optarg;
+      stoponerror = 1;
+      progress_indicators = 0;
+      break;
+    case 'P':
+      program = optarg;
+      break;
+    case 'R':
+      nrequests = atoi(optarg);
+      break;
+    case 's':
+      subsystem = optarg;
+      break;
+    case 'S':
+      sftpversion = atoi(optarg);
+      break;
+    case '1':
+      sshversion = 1;
+      break;
+    case '2':
+      sshversion = 2;
+      break;
+    case 'C':
+      compress = 1;
+      break;
+    case 'F':
+      sshconf = optarg;
+      break;
+    case 'o':
+      sshoptions[nsshoptions++] = optarg;
+      break;
+    case 'v':
+      sshverbose++;
+      break;
+    case 'd':
+      sftp_debugging = 1;
+      break;
+    case 'D':
+      sftp_debugging = 1;
+      sftp_debugpath = optarg;
+      break;
+    case 256:
+      quirk_reverse_symlink = 1;
+      break;
+    case 257:
+      stoponerror = 1;
+      break;
+    case 258:
+      stoponerror = 0;
+      break;
+    case 259:
+      progress_indicators = 1;
+      break;
+    case 260:
+      progress_indicators = 0;
+      break;
+    case 261:
+      echo = 1;
+      break;
+    case 262:
+      signal(SIGPIPE, SIG_DFL);
+      break; /* stupid python */
+    case 263:
+      sftpversion = atoi(optarg);
+      forceversion = 1;
+      break;
+    case 264:
+      program_debugpath = optarg;
+      break;
+    case 'H':
+      host = optarg;
+      break;
+    case 'p':
+      port = optarg;
+      break;
 #if HAVE_GETADDRINFO
-    case '4': hints.ai_family = PF_INET; break;
-    case '6': hints.ai_family = PF_INET6; break;
+    case '4':
+      hints.ai_family = PF_INET;
+      break;
+    case '6':
+      hints.ai_family = PF_INET6;
+      break;
 #endif
-    default: exit(1);
+    default:
+      exit(1);
     }
   }
 
@@ -2967,28 +2836,27 @@ int main(int argc, char **argv) {
     buffersize = 1048576;
 
   if((sftpversion < 3 || sftpversion > 6) && !forceversion)
-    fatal("unknown SFTP version %d", sftpversion);
-  
+    sftp_fatal("unknown SFTP version %d", sftpversion);
+
   if(host || port) {
 #if HAVE_GETADDRINFO
     struct addrinfo *res;
     int rc, fd;
 
     if(!(host && port) || program || subsystem)
-      fatal("inconsistent options");
+      sftp_fatal("inconsistent options");
     if((rc = getaddrinfo(host, port, &hints, &res)))
-      fatal("error resolving host %s port %s: %s",
-            host, port, gai_strerror(rc));
-    if((fd = socket(res->ai_family, res->ai_socktype,
-                    res->ai_protocol)) < 0)
-      fatal("error calling socket: %s", strerror(errno));
+      sftp_fatal("error resolving host %s port %s: %s", host, port,
+                 gai_strerror(rc));
+    if((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
+      sftp_fatal("error calling socket: %s", strerror(errno));
     if(connect(fd, res->ai_addr, res->ai_addrlen) < 0)
-      fatal("error connecting to host %s port %s: %s",
-            host, port, strerror(errno));
+      sftp_fatal("error connecting to host %s port %s: %s", host, port,
+                 strerror(errno));
     sftpin = sftpout = fd;
 #else
     /* It's hardly a core feature... */
-    fatal("--host is not supported on this platform");
+    sftp_fatal("--host is not supported on this platform");
 #endif
   } else {
     const char *cmdline[2048];
@@ -3004,7 +2872,7 @@ int main(int argc, char **argv) {
       }
     } else {
       if(optind >= argc)
-        fatal("missing USER@HOST argument");
+        sftp_fatal("missing USER@HOST argument");
       if(dropbear) {
         cmdline[ncmdline++] = "dbclient";
       } else {
@@ -3031,40 +2899,39 @@ int main(int argc, char **argv) {
       cmdline[ncmdline++] = subsystem ? subsystem : "sftp";
     }
     cmdline[ncmdline] = 0;
-    xpipe(ip);
-    xpipe(op);
-    if(!(pid = xfork())) {
-      xclose(ip[0]);
-      xclose(op[1]);
-      xdup2(ip[1], 1);
-      xdup2(op[0], 0);
+    sftp_xpipe(ip);
+    sftp_xpipe(op);
+    if(!(pid = sftp_xfork())) {
+      sftp_xclose(ip[0]);
+      sftp_xclose(op[1]);
+      sftp_xdup2(ip[1], 1);
+      sftp_xdup2(op[0], 0);
       execvp(cmdline[0], (void *)cmdline);
-      fatal("executing %s: %s", cmdline[0], strerror(errno));
+      sftp_fatal("executing %s: %s", cmdline[0], strerror(errno));
     }
-    xclose(ip[1]);
-    xclose(op[0]);
+    sftp_xclose(ip[1]);
+    sftp_xclose(op[0]);
     sftpin = ip[0];
     sftpout = op[1];
   }
   fakejob.a = sftp_alloc_init(&allocator);
   fakejob.worker = &fakeworker;
-  if((fakeworker.utf8_to_local = iconv_open(nl_langinfo(CODESET), "UTF-8"))
-     == (iconv_t)-1)
-    fatal("error calling iconv_open: %s", strerror(errno));
-  if((fakeworker.local_to_utf8 = iconv_open("UTF-8", nl_langinfo(CODESET)))
-     == (iconv_t)-1)
-    fatal("error calling iconv_open: %s", strerror(errno));
+  if((fakeworker.utf8_to_local = iconv_open(nl_langinfo(CODESET), "UTF-8")) ==
+     (iconv_t)-1)
+    sftp_fatal("error calling iconv_open: %s", strerror(errno));
+  if((fakeworker.local_to_utf8 = iconv_open("UTF-8", nl_langinfo(CODESET))) ==
+     (iconv_t)-1)
+    sftp_fatal("error calling iconv_open: %s", strerror(errno));
 
   if(sftp_init())
     return 1;
-  
 
   if(batchfile) {
     FILE *fp;
 
     inputpath = batchfile;
     if(!(fp = fopen(batchfile, "r")))
-      fatal("error opening %s: %s", batchfile, strerror(errno));
+      sftp_fatal("error opening %s: %s", batchfile, strerror(errno));
     process(0, fp);
   } else {
     inputpath = "stdin";
diff --git a/sftpclient.h b/sftpclient.h
index dad4485..d3f2bdc 100644
--- a/sftpclient.h
+++ b/sftpclient.h
@@ -19,13 +19,13 @@
  */
 
 #ifndef SFTPCLIENT_H
-#define SFTPCLIENT_H
+#  define SFTPCLIENT_H
 
-#define CLIENT 1
+#  define CLIENT 1
 
-#include "sftpcommon.h"
+#  include "sftpcommon.h"
 
-#include <sys/types.h>
+#  include <sys/types.h>
 
 #endif /* SFTPCLIENT_H */
 
diff --git a/sftpcommon.h b/sftpcommon.h
index 45a3d25..5785254 100644
--- a/sftpcommon.h
+++ b/sftpcommon.h
@@ -19,58 +19,66 @@
  */
 
 #ifndef SFTPCOMMON_H
-#define SFTPCOMMON_H
+#  define SFTPCOMMON_H
 
 /** @file sftpcommon.h @brief Common definitions */
 
-#include <config.h>
-#include <inttypes.h>
-#include <sys/types.h>
+#  include <config.h>
+#  include <inttypes.h>
+#  include <sys/types.h>
 
-#if HAVE_ENDIAN_H
-# include <endian.h>
-#endif
+#  if HAVE_ENDIAN_H
+#    include <endian.h>
+#  endif
 
-#ifndef ASM
-# define ASM 1
-#endif
+#  ifndef ASM
+#    define ASM 1
+#  endif
 
-#if __GNUC__ && __amd64__ && ASM
+#  if __GNUC__ && __amd64__ && ASM
 /** @brief Byte-swap a 64-bit value */
-#define BSWAP64(N)				\
-  ({uint64_t __n = (N); __asm__("bswap %0" : "+q"(__n)); __n;})
-#endif
+#    define BSWAP64(N)                                                         \
+      ({                                                                       \
+        uint64_t __n = (N);                                                    \
+        __asm__("bswap %0" : "+q"(__n));                                       \
+        __n;                                                                   \
+      })
+#  endif
 
-#if __GNUC__ && !defined BSWAP64
+#  if __GNUC__ && !defined BSWAP64
 /** @brief Byte-swap a 64-bit value */
-#define BSWAP64(N) \
-  ({uint64_t __n = (N); __n = ntohl(__n >> 32) | ((uint64_t)ntohl(__n) << 32); __n;})
-#endif
+#    define BSWAP64(N)                                                         \
+      ({                                                                       \
+        uint64_t __n = (N);                                                    \
+        __n = ntohl(__n >> 32) | ((uint64_t)ntohl(__n) << 32);                 \
+        __n;                                                                   \
+      })
+#  endif
 
-#if WORDS_BIGENDIAN
+#  if WORDS_BIGENDIAN
 /** @brief Convert a 64-bit value to network byte order */
-# define NTOHLL(n) (n)
+#    define NTOHLL(n) (n)
 /** @brief Convert a 64-bit value to host byte order */
-# define HTONLL(n) (n)
-#endif
+#    define HTONLL(n) (n)
+#  endif
 
-#if HAVE_DECL_BE64TOH && !defined NTOHLL
+#  if HAVE_DECL_BE64TOH && !defined NTOHLL
 /** @brief Convert a 64-bit value to network byte order */
-# define NTOHLL be64toh
-#endif
-#if HAVE_DECL_HTOBE64 && !defined HTONLL
+#    define NTOHLL be64toh
+#  endif
+#  if HAVE_DECL_HTOBE64 && !defined HTONLL
 /** @brief Convert a 64-bit value to host byte order */
-#define HTONLL htobe64
-#endif
+#    define HTONLL htobe64
+#  endif
 
-#if defined BSWAP64 && !defined NTOHLL
+#  if defined BSWAP64 && !defined NTOHLL
 /** @brief Convert a 64-bit value to network byte order */
-# define NTOHLL BSWAP64
-#endif
-#if defined BSWAP64 && !defined HTONLL
+#    define NTOHLL BSWAP64
+#  endif
+#  if defined BSWAP64 && !defined HTONLL
 /** @brief Convert a 64-bit value to host byte order */
-# define HTONLL BSWAP64
-#endif
+#    define HTONLL BSWAP64
+#  endif
 
 struct queue;
 struct allocator;
@@ -86,6 +94,22 @@ struct stat;
  */
 const char *status_to_string(uint32_t status);
 
+/** @brief Possible SFTP service states */
+enum sftp_state {
+  sftp_state_run = 0,
+  sftp_state_stop = 1,
+};
+
+/** @brief Get the current SFTP service state
+ * @return State value
+ */
+enum sftp_state sftp_state_get(void);
+
+/** @brief Set the SFTP service state
+ * @param s New state value
+ */
+void sftp_state_set(enum sftp_state s);
+
 #endif /* SFTPCOMMON_H */
 
 /*
diff --git a/sftpserver.c b/sftpserver.c
index c23a8b9..e99aded 100644
--- a/sftpserver.c
+++ b/sftpserver.c
@@ -51,17 +51,17 @@
 #include <syslog.h>
 #include <netinet/in.h>
 #if HAVE_SYS_PRCTL_H
-# include <sys/prctl.h>
+#  include <sys/prctl.h>
 #endif
 
 /* Linux and BSD have daemon() but other UNIX platforms tend not to */
-#if ! HAVE_DAEMON
+#if !HAVE_DAEMON
 int daemon(int, int);
 #endif
 
 /* LOG_FTP doesn't exist everywhere */
 #ifndef LOG_FTP
-# define LOG_FTP LOG_DAEMON
+#  define LOG_FTP LOG_DAEMON
 #endif
 
 /* Forward declarations */
@@ -77,10 +77,7 @@ static const char *local_encoding;
 #if NTHREADS > 1
 /** @brief Queue-specific callbacks for processing SFTP requests */
 static const struct queuedetails workqueue_details = {
-  worker_init,
-  process_sftpjob,
-  worker_cleanup
-};
+    worker_init, process_sftpjob, worker_cleanup};
 #endif
 
 const struct sftpprotocol *protocol = &sftp_preinit;
@@ -89,48 +86,47 @@ const char sendtype[] = "response";
 /* Options */
 
 static const struct option options[] = {
-  { "help", no_argument, 0, 'h' },
-  { "version", no_argument, 0, 'V' },
-  { "debug", no_argument, 0, 'd' },
-  { "debug-file", required_argument, 0, 'D' },
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"debug", no_argument, 0, 'd'},
+    {"debug-file", required_argument, 0, 'D'},
 #if DAEMON
-  { "chroot", required_argument, 0, 'r' },
-  { "user", required_argument, 0, 'u' },
-  { "listen", required_argument, 0, 'L' },
-  { "host", required_argument, 0, 'H' },
-  { "background", no_argument, 0, 'b' },
-  { "ipv4", no_argument, 0, '4' },
-  { "ipv6", no_argument, 0, '6' },
+    {"chroot", required_argument, 0, 'r'},
+    {"user", required_argument, 0, 'u'},
+    {"listen", required_argument, 0, 'L'},
+    {"host", required_argument, 0, 'H'},
+    {"background", no_argument, 0, 'b'},
+    {"ipv4", no_argument, 0, '4'},
+    {"ipv6", no_argument, 0, '6'},
 #endif
-  { "readonly", no_argument, 0, 'R' },
-  { 0, 0, 0, 0 }
-};
+    {"readonly", no_argument, 0, 'R'},
+    {0, 0, 0, 0}};
 
 /* display usage message and terminate */
 static void attribute((noreturn)) help(void) {
-  xprintf("Usage:\n"
-          "  gesftpserver [OPTIONS]\n"
-          "\n"
-          "Green End SFTP server.  Not intended for interactive use!\n"
-          "\n");
-  xprintf("Options:\n"
-          "  --help, -h               Display usage message\n"
-          "  --version, -V            Display version number\n"
+  sftp_xprintf("Usage:\n"
+               "  gesftpserver [OPTIONS]\n"
+               "\n"
+               "Green End SFTP server.  Not intended for interactive use!\n"
+               "\n");
+  sftp_xprintf("Options:\n"
+               "  --help, -h               Display usage message\n"
+               "  --version, -V            Display version number\n"
 #if DAEMON
-          "  --chroot, -r PATH        Change root to PATH\n"
-          "  --user, -u USER          Change to user USER\n"
-          "  --listen, -L PORT        Listen on PORT\n"
-          "  --host, -H HOSTNAME      Bind to HOSTNAME (default *)\n"
-          "  -4|-6                    Force IPv4 or IPv6 for --listen\n"
-          "  --background, -b         Daemonize\n"
+               "  --chroot, -r PATH        Change root to PATH\n"
+               "  --user, -u USER          Change to user USER\n"
+               "  --listen, -L PORT        Listen on PORT\n"
+               "  --host, -H HOSTNAME      Bind to HOSTNAME (default *)\n"
+               "  -4|-6                    Force IPv4 or IPv6 for --listen\n"
+               "  --background, -b         Daemonize\n"
 #endif
-          "  --readonly, -R           Read-only mode\n");
+               "  --readonly, -R           Read-only mode\n");
   exit(0);
 }
 
 /* display version number and terminate */
 static void attribute((noreturn)) version(void) {
-  xprintf("Green End SFTP server version %s\n", VERSION);
+  sftp_xprintf("Green End SFTP server version %s\n", VERSION);
   exit(0);
 }
 
@@ -150,7 +146,9 @@ static uint32_t sftp_init(struct sftpjob *job) {
     return SSH_FX_FAILURE;
   pcheck(sftp_parse_uint32(job, &version));
   switch(version) {
-  case 0: case 1: case 2:
+  case 0:
+  case 1:
+  case 2:
     return SSH_FX_OP_UNSUPPORTED;
   case 3:
     protocol = &sftp_v3;
@@ -188,17 +186,15 @@ static uint32_t sftp_init(struct sftpjob *job) {
     /* draft-ietf-secsh-filexfer-05.txt 4.4 */
     sftp_send_string(job->worker, "supported");
     offset = sftp_send_sub_begin(job->worker);
-    sftp_send_uint32(job->worker, (SSH_FILEXFER_ATTR_SIZE
-                              |SSH_FILEXFER_ATTR_PERMISSIONS
-                              |SSH_FILEXFER_ATTR_ACCESSTIME
-                              |SSH_FILEXFER_ATTR_MODIFYTIME
-                              |SSH_FILEXFER_ATTR_OWNERGROUP
-                              |SSH_FILEXFER_ATTR_SUBSECOND_TIMES));
-    sftp_send_uint32(job->worker, 0);         /* supported-attribute-bits */
-    sftp_send_uint32(job->worker, (SSH_FXF_ACCESS_DISPOSITION
-                              |SSH_FXF_APPEND_DATA
-                              |SSH_FXF_APPEND_DATA_ATOMIC
-                              |SSH_FXF_TEXT_MODE));
+    sftp_send_uint32(
+        job->worker,
+        (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+         SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+         SSH_FILEXFER_ATTR_OWNERGROUP | SSH_FILEXFER_ATTR_SUBSECOND_TIMES));
+    sftp_send_uint32(job->worker, 0); /* supported-attribute-bits */
+    sftp_send_uint32(job->worker,
+                     (SSH_FXF_ACCESS_DISPOSITION | SSH_FXF_APPEND_DATA |
+                      SSH_FXF_APPEND_DATA_ATOMIC | SSH_FXF_TEXT_MODE));
     sftp_send_uint32(job->worker, 0xFFFFFFFF);
     /* If we send a non-0 max-read-size then we promise to return that many
      * bytes if asked for it and to mean EOF or error if we return less.
@@ -218,29 +214,27 @@ static uint32_t sftp_init(struct sftpjob *job) {
     /* draft-ietf-secsh-filexfer-13.txt 5.4 */
     sftp_send_string(job->worker, "supported2");
     offset = sftp_send_sub_begin(job->worker);
-    sftp_send_uint32(job->worker, (SSH_FILEXFER_ATTR_SIZE
-                              |SSH_FILEXFER_ATTR_PERMISSIONS
-                              |SSH_FILEXFER_ATTR_ACCESSTIME
-                              |SSH_FILEXFER_ATTR_MODIFYTIME
-                              |SSH_FILEXFER_ATTR_OWNERGROUP
-                              |SSH_FILEXFER_ATTR_SUBSECOND_TIMES));
+    sftp_send_uint32(
+        job->worker,
+        (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+         SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+         SSH_FILEXFER_ATTR_OWNERGROUP | SSH_FILEXFER_ATTR_SUBSECOND_TIMES));
     /* Note - the client is invited to only send these bits, rather than
      * promised that we never send anything else.  Therefore 'supported-' is a
      * misnomer.  In particular we will send SSH_FILEXFER_ATTR_CTIME but cannot
      * set the ctime of files and so follow the SHOULD that tells us to reject
      * attempts to do so. */
-    sftp_send_uint32(job->worker, 0);         /* supported-attribute-bits */
-    sftp_send_uint32(job->worker, (SSH_FXF_ACCESS_DISPOSITION
-                              |SSH_FXF_APPEND_DATA
-                              |SSH_FXF_APPEND_DATA_ATOMIC
-                              |SSH_FXF_TEXT_MODE
-                              |SSH_FXF_NOFOLLOW
-                              |SSH_FXF_DELETE_ON_CLOSE)); /* supported-open-flags */
-    sftp_send_uint32(job->worker, 0xFFFFFFFF); /* supported-access-mask */
-    sftp_send_uint32(job->worker, 0);        /* max-read-size - see above */
-    sftp_send_uint16(job->worker, 1);        /* supported-open-block-vector */
-    sftp_send_uint16(job->worker, 1);        /* supported-block-vector */
-    sftp_send_uint32(job->worker, 0);        /* attrib-extension-count */
+    sftp_send_uint32(job->worker, 0); /* supported-attribute-bits */
+    sftp_send_uint32(job->worker,
+                     (SSH_FXF_ACCESS_DISPOSITION | SSH_FXF_APPEND_DATA |
+                      SSH_FXF_APPEND_DATA_ATOMIC | SSH_FXF_TEXT_MODE |
+                      SSH_FXF_NOFOLLOW |
+                      SSH_FXF_DELETE_ON_CLOSE)); /* supported-open-flags */
+    sftp_send_uint32(job->worker, 0xFFFFFFFF);   /* supported-access-mask */
+    sftp_send_uint32(job->worker, 0);            /* max-read-size - see above */
+    sftp_send_uint16(job->worker, 1); /* supported-open-block-vector */
+    sftp_send_uint16(job->worker, 1); /* supported-block-vector */
+    sftp_send_uint32(job->worker, 0); /* attrib-extension-count */
     /* attrib-extensions would go here */
     sftp_send_uint32(job->worker, protocol->nextensions); /* extension-count */
     for(n = 0; n < protocol->nextensions; ++n)
@@ -287,27 +281,24 @@ static uint32_t sftp_init(struct sftpjob *job) {
 }
 
 /** @brief Requests supported prior to initialization */
-static const struct sftpcmd sftppreinittab[] = {
-  { SSH_FXP_INIT, sftp_init }
-};
+static const struct sftpcmd sftppreinittab[] = {{SSH_FXP_INIT, sftp_init}};
 
 /** @brief Protocol supported prior to initialization
  *
  * Only @ref SSH_FXP_INIT is supported at first. */
-const struct sftpprotocol sftp_preinit = {
-  sizeof sftppreinittab / sizeof (struct sftpcmd),
-  sftppreinittab,
-  3,
-  0xFFFFFFFF,                           /* never used */
-  SSH_FX_OP_UNSUPPORTED,
-  0,
-  0,
-  0,
-  sftp_v3_encode,
-  0,
-  0,
-  0
-};
+const struct sftpprotocol sftp_preinit = {sizeof sftppreinittab /
+                                              sizeof(struct sftpcmd),
+                                          sftppreinittab,
+                                          3,
+                                          0xFFFFFFFF, /* never used */
+                                          SSH_FX_OP_UNSUPPORTED,
+                                          0,
+                                          0,
+                                          0,
+                                          sftp_v3_encode,
+                                          0,
+                                          0,
+                                          0};
 
 /* Worker setup/teardown */
 
@@ -315,18 +306,16 @@ const struct sftpprotocol sftp_preinit = {
  * @return Initialized worker state
  */
 static void *worker_init(void) {
-  struct worker *w = xmalloc(sizeof *w);
+  struct worker *w = sftp_xmalloc(sizeof *w);
 
-  memset(w, 0, sizeof *w);
+  sftp_memset(w, 0, sizeof *w);
   w->buffer = 0;
-  if((w->utf8_to_local = iconv_open(local_encoding, "UTF-8"))
-     == (iconv_t)-1)
-    fatal("error calling iconv_open(%s,UTF-8): %s",
-          local_encoding, strerror(errno));
-  if((w->local_to_utf8 = iconv_open("UTF-8", local_encoding))
-     == (iconv_t)-1)
-    fatal("error calling iconv_open(UTF-8,%s): %s",
-          local_encoding, strerror(errno));
+  if((w->utf8_to_local = iconv_open(local_encoding, "UTF-8")) == (iconv_t)-1)
+    sftp_fatal("error calling iconv_open(%s,UTF-8): %s", local_encoding,
+               strerror(errno));
+  if((w->local_to_utf8 = iconv_open("UTF-8", local_encoding)) == (iconv_t)-1)
+    sftp_fatal("error calling iconv_open(UTF-8,%s): %s", local_encoding,
+               strerror(errno));
   return w;
 }
 
@@ -355,7 +344,7 @@ static void process_sftpjob(void *jv, void *wdv, struct allocator *a) {
   struct sftpjob *const job = jv;
   int l, r, type = 0;
   uint32_t status, rc;
-  
+
   job->a = a;
   job->id = 0;
   job->worker = wdv;
@@ -381,7 +370,7 @@ static void process_sftpjob(void *jv, void *wdv, struct allocator *a) {
   while(l <= r) {
     const int m = (l + r) / 2;
     const int mtype = protocol->commands[m].type;
-    
+
     if(type < mtype)
       r = m - 1;
     else if(type > mtype)
@@ -393,8 +382,11 @@ static void process_sftpjob(void *jv, void *wdv, struct allocator *a) {
       status = protocol->commands[m].handler(job);
       /* Send a response if necessary */
       switch(status) {
-      case HANDLER_RESPONDED: break;
-      default: sftp_send_status(job, status, 0); break;
+      case HANDLER_RESPONDED:
+        break;
+      default:
+        sftp_send_status(job, status, 0);
+        break;
       }
       goto done;
     }
@@ -440,7 +432,7 @@ int main(int argc, char **argv) {
   int daemonize = 0;
   struct addrinfo hints;
 
-  memset(&hints, 0, sizeof hints);
+  sftp_memset(&hints, 0, sizeof hints);
   hints.ai_flags = AI_PASSIVE;
   hints.ai_family = PF_UNSPEC;
   hints.ai_socktype = SOCK_STREAM;
@@ -453,9 +445,9 @@ int main(int argc, char **argv) {
   if(strstr(bn, "-debug")) {
     const char *home = getenv("HOME");
 
-    sftp_debugpath = xmalloc(strlen(home) + 40);
-    sprintf((char *)sftp_debugpath, "%s/.gesftpserver.%ju", 
-            home, (uintmax_t)getpid());
+    sftp_debugpath = sftp_xmalloc(strlen(home) + 40);
+    sprintf((char *)sftp_debugpath, "%s/.gesftpserver.%ju", home,
+            (uintmax_t)getpid());
     sftp_debugging = 1;
   }
   /* Run in readonly mode */
@@ -465,31 +457,54 @@ int main(int argc, char **argv) {
   /* We need I18N support for filename encoding */
   setlocale(LC_CTYPE, "");
   local_encoding = nl_langinfo(CODESET);
-  
-  while((n = getopt_long(argc, argv, "hVdD:r:u:H:L:b46R",
-			 options, 0)) >= 0) {
+
+  while((n = getopt_long(argc, argv, "hVdD:r:u:H:L:b46R", options, 0)) >= 0) {
     switch(n) {
-    case 'h': help();
-    case 'V': version();
-    case 'd': sftp_debugging = 1; break;
-    case 'D': sftp_debugging = 1; sftp_debugpath = optarg; break;
+    case 'h':
+      help();
+    case 'V':
+      version();
+    case 'd':
+      sftp_debugging = 1;
+      break;
+    case 'D':
+      sftp_debugging = 1;
+      sftp_debugpath = optarg;
+      break;
 #if DAEMON
-    case 'r': root = optarg; break;
-    case 'u': user = optarg; break;
-    case 'H': host = optarg; break;
-    case 'L': port = optarg; break;
-    case 'b': daemonize = 1; break;
-    case '4': hints.ai_family = PF_INET; break;
-    case '6': hints.ai_family = PF_INET6; break;
+    case 'r':
+      root = optarg;
+      break;
+    case 'u':
+      user = optarg;
+      break;
+    case 'H':
+      host = optarg;
+      break;
+    case 'L':
+      port = optarg;
+      break;
+    case 'b':
+      daemonize = 1;
+      break;
+    case '4':
+      hints.ai_family = PF_INET;
+      break;
+    case '6':
+      hints.ai_family = PF_INET6;
+      break;
 #endif
-    case 'R': readonly = 1; break;
-    default: exit(1);
+    case 'R':
+      readonly = 1;
+      break;
+    default:
+      exit(1);
     }
   }
 
 #if DAEMON
   if(daemonize && !port)
-    fatal("--background requires --port");
+    sftp_fatal("--background requires --port");
 #endif
 
   /* If writes to the client fail then we'll get EPIPE.  Arguably it might
@@ -510,16 +525,16 @@ int main(int argc, char **argv) {
 
 #if HAVE_PRCTL
   if(prctl(PR_SET_DUMPABLE, 0L) < 0)
-    fatal("error calling prctl: %s", strerror(errno));
+    sftp_fatal("error calling prctl: %s", strerror(errno));
 #endif
 
 #if DAEMON
   if(user) {
     /* Look up the user */
     if(!(pw = getpwnam(user)))
-      fatal("no such user as %s", user);
+      sftp_fatal("no such user as %s", user);
     if(initgroups(user, pw->pw_gid))
-      fatal("error calling initgroups: %s", strerror(errno));
+      sftp_fatal("error calling initgroups: %s", strerror(errno));
   }
 
   if(port) {
@@ -532,60 +547,59 @@ int main(int argc, char **argv) {
     sa.sa_flags = SA_RESTART;
     sigemptyset(&sa.sa_mask);
     if(sigaction(SIGCHLD, &sa, 0) < 0)
-      fatal("error calling sigaction: %s", strerror(errno));
+      sftp_fatal("error calling sigaction: %s", strerror(errno));
     if((rc = getaddrinfo(host, port, &hints, &res))) {
       if(host)
-        fatal("error resolving host %s port %s: %s",
-              host, port, gai_strerror(rc));
+        sftp_fatal("error resolving host %s port %s: %s", host, port,
+                   gai_strerror(rc));
       else
-        fatal("error resolving port %s: %s",
-              port, gai_strerror(rc));
+        sftp_fatal("error resolving port %s: %s", port, gai_strerror(rc));
     }
-    if((listenfd = socket(res->ai_family, res->ai_socktype,
-                          res->ai_protocol)) < 0)
-      fatal("error calling socket: %s", strerror(errno));
-    if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &one,  sizeof one) < 0)
-      fatal("error calling setsockopt: %s", strerror(errno));
+    if((listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) <
+       0)
+      sftp_fatal("error calling socket: %s", strerror(errno));
+    if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) < 0)
+      sftp_fatal("error calling setsockopt: %s", strerror(errno));
     if(bind(listenfd, res->ai_addr, res->ai_addrlen) < 0)
-      fatal("error calling socket: %s", strerror(errno));
+      sftp_fatal("error calling socket: %s", strerror(errno));
     if(listen(listenfd, SOMAXCONN) < 0)
-      fatal("error calling listen: %s", strerror(errno));
+      sftp_fatal("error calling listen: %s", strerror(errno));
   } else if(host)
-    fatal("--host makes no sense without --port");
+    sftp_fatal("--host makes no sense without --port");
 
   if((cd = iconv_open(local_encoding, "UTF-8")) == (iconv_t)-1)
-    fatal("error calling iconv_open(%s,UTF-8): %s",
-          local_encoding, strerror(errno));
+    sftp_fatal("error calling iconv_open(%s,UTF-8): %s", local_encoding,
+               strerror(errno));
   iconv_close(cd);
   if((cd = iconv_open("UTF-8", local_encoding)) == (iconv_t)-1)
-    fatal("error calling iconv_open(UTF-8, %s): %s",
-          local_encoding, strerror(errno));
+    sftp_fatal("error calling iconv_open(UTF-8, %s): %s", local_encoding,
+               strerror(errno));
   iconv_close(cd);
-  
+
   if(root) {
     /* Enter our chroot */
     if(chdir(root) < 0)
-      fatal("error calling chdir %s: %s", root, strerror(errno));
+      sftp_fatal("error calling chdir %s: %s", root, strerror(errno));
     if(chroot(".") < 0)
-      fatal("error calling chroot: %s", strerror(errno));
+      sftp_fatal("error calling chroot: %s", strerror(errno));
   }
 
   if(user) {
     /* Become the right user */
     assert(pw != 0);
     if(setgid(pw->pw_gid) < 0)
-      fatal("error calling setgid: %s", strerror(errno));
+      sftp_fatal("error calling setgid: %s", strerror(errno));
     if(setuid(pw->pw_uid) < 0)
-      fatal("error calling setuid: %s", strerror(errno));
+      sftp_fatal("error calling setuid: %s", strerror(errno));
     if(setuid(0) >= 0)
-      fatal("setuid(0) unexpectedly succeeded");
+      sftp_fatal("setuid(0) unexpectedly succeeded");
   }
-  
+
   if(daemonize) {
     openlog(bn, LOG_PID, LOG_FTP);
-    log_syslog = 1;
+    sftp_log_syslog = 1;
     if(daemon(0, 0) < 0)
-      fatal("error calling daemon: %s", strerror(errno));
+      sftp_fatal("error calling daemon: %s", strerror(errno));
   }
 
   if(!port) {
@@ -600,7 +614,7 @@ int main(int argc, char **argv) {
       } addr;
       socklen_t addrlen = sizeof addr;
       int fd;
-    
+
       if((fd = accept(listenfd, &addr.sa, &addrlen)) >= 0) {
         switch(fork()) {
         case -1:
@@ -610,14 +624,12 @@ int main(int argc, char **argv) {
           sleep(60);
           break;
         case 0:
-          forked();
-          signal(SIGCHLD, SIG_DFL);       /* XXX */
-          if(dup2(fd, 0) < 0
-             || dup2(fd, 1) < 0)
-            fatal("dup2: %s", strerror(errno));
-          if(close(fd) < 0
-             || close(listenfd) < 0)
-            fatal("close: %s", strerror(errno));
+          sftp_forked();
+          signal(SIGCHLD, SIG_DFL); /* XXX */
+          if(dup2(fd, 0) < 0 || dup2(fd, 1) < 0)
+            sftp_fatal("dup2: %s", strerror(errno));
+          if(close(fd) < 0 || close(listenfd) < 0)
+            sftp_fatal("close: %s", strerror(errno));
           sftp_service();
           _exit(0);
         default:
@@ -641,21 +653,22 @@ static void sftp_service(void) {
   uint32_t len;
   struct sftpjob *job;
   struct allocator a;
-  void *const wdv = worker_init(); 
+  void *const wdv = worker_init();
   D(("gesftpserver %s starting up", VERSION));
   /* draft -13 s7.6 "The server SHOULD NOT apply a 'umask' to the mode
    * bits". */
   umask(0);
-  while(!do_read(0, &len, sizeof len)) {
-    job = xmalloc(sizeof *job);
+  while(sftp_state_get() != sftp_state_stop &&
+        !sftp_xread(0, &len, sizeof len)) {
+    job = sftp_xmalloc(sizeof *job);
     job->len = ntohl(len);
     if(!job->len || job->len > MAXREQUEST)
-      fatal("invalid request size");
-    job->data = xmalloc(job->len);
-    if(do_read(0, job->data, job->len))
+      sftp_fatal("invalid request size");
+    job->data = sftp_xmalloc(job->len);
+    if(sftp_xread(0, job->data, job->len))
       /* Job data missing or truncated - the other end is not playing the game
        * fair so we give up straight away */
-      fatal("read error: unexpected eof");
+      sftp_fatal("read error: unexpected eof");
     if(sftp_debugging) {
       D(("request:"));
       sftp_debug_hexdump(job->data, job->len);
diff --git a/sftpserver.h b/sftpserver.h
index b3d7657..2ad6eb3 100644
--- a/sftpserver.h
+++ b/sftpserver.h
@@ -21,50 +21,48 @@
 /** @file sftpserver.h @brief SFTP server parameters and common declarations */
 
 #ifndef SFTPSERVER_H
-#define SFTPSERVER_H
+#  define SFTPSERVER_H
 
-#include "sftpcommon.h"
+#  include "sftpcommon.h"
 
-#include <sys/types.h>
+#  include <sys/types.h>
 
-#ifndef MAXNAMES
+#  ifndef MAXNAMES
 /** @brief Maximum size of an @ref SSH_FXP_READDIR response */
-# define MAXNAMES 32
-#endif
+#    define MAXNAMES 32
+#  endif
 
-#ifndef MAXHANDLES
+#  ifndef MAXHANDLES
 /** @brief Maximum number of concurrent handles */
-# define MAXHANDLES 128
-#endif
+#    define MAXHANDLES 128
+#  endif
 
-#ifndef MAXREAD
+#  ifndef MAXREAD
 /** @brief Maximum read size */
-# define MAXREAD 1048576
-#endif
+#    define MAXREAD 1048576
+#  endif
 
-#ifndef MAXREQUEST
+#  ifndef MAXREQUEST
 /** @brief Maximum request size */
-# define MAXREQUEST 1048576
-#endif
+#    define MAXREQUEST 1048576
+#  endif
 
-#ifndef DEFAULT_PERMISSIONS
+#  ifndef DEFAULT_PERMISSIONS
 /** @brief Default file permissions */
-# define DEFAULT_PERMISSIONS 0755
-#endif
+#    define DEFAULT_PERMISSIONS 0755
+#  endif
 
-#ifndef NTHREADS
+#  ifndef NTHREADS
 /** @brief Number of threads */
-# define NTHREADS 4
-#endif
+#    define NTHREADS 4
+#  endif
 
 /** @brief Send an @ref SSH_FXP_STATUS message
  * @param job Job
  * @param status Status code
  * @param msg Human-readable message
  */
-void sftp_send_status(struct sftpjob *job, 
-                      uint32_t status,
-                      const char *msg);
+void sftp_send_status(struct sftpjob *job, uint32_t status, const char *msg);
 
 /** @brief @ref SSH_FXP_INIT stub for use after initialization
  * @param job Job
@@ -160,8 +158,8 @@ uint32_t sftp_vany_extended(struct sftpjob *job);
  *
  * This is for protocols 4 and above.
  */
-void sftp_v456_sendnames(struct sftpjob *job, 
-                         int nnames, const struct sftpattr *names);
+void sftp_v456_sendnames(struct sftpjob *job, int nnames,
+                         const struct sftpattr *names);
 
 /** @brief Send file attributes
  * @param job Job
@@ -170,8 +168,7 @@ void sftp_v456_sendnames(struct sftpjob *job,
  *
  * This is for protocols 4 and above.
  */
-void sftp_v456_sendattrs(struct sftpjob *job,
-                         const struct sftpattr *attrs);
+void sftp_v456_sendattrs(struct sftpjob *job, const struct sftpattr *attrs);
 
 /** @brief Parse file attributes
  * @param job Job
diff --git a/stat.c b/stat.c
index bb36430..def7853 100644
--- a/stat.c
+++ b/stat.c
@@ -35,40 +35,52 @@
 #include <sys/time.h>
 #include <unistd.h>
 
-#if ! HAVE_FUTIMES
+#if !HAVE_FUTIMES
 int futimes(int fd, const struct timeval *times);
 #endif
 
-void sftp_stat_to_attrs(struct allocator *a,
-		   const struct stat *sb, struct sftpattr *attrs,
-                   uint32_t flags, const char *path) {
-  memset(attrs, 0, sizeof *attrs);
-  attrs->valid = (SSH_FILEXFER_ATTR_SIZE
-		  |SSH_FILEXFER_ATTR_PERMISSIONS
-		  |SSH_FILEXFER_ATTR_ACCESSTIME
-		  |SSH_FILEXFER_ATTR_MODIFYTIME
-		  |SSH_FILEXFER_ATTR_UIDGID
-		  |SSH_FILEXFER_ATTR_ALLOCATION_SIZE
-		  |SSH_FILEXFER_ATTR_LINK_COUNT
-		  |SSH_FILEXFER_ATTR_CTIME
-                  |SSH_FILEXFER_ATTR_BITS);
+void sftp_stat_to_attrs(struct allocator *a, const struct stat *sb,
+                        struct sftpattr *attrs, uint32_t flags,
+                        const char *path) {
+  sftp_memset(attrs, 0, sizeof *attrs);
+  attrs->valid = (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+                  SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+                  SSH_FILEXFER_ATTR_UIDGID | SSH_FILEXFER_ATTR_ALLOCATION_SIZE |
+                  SSH_FILEXFER_ATTR_LINK_COUNT | SSH_FILEXFER_ATTR_CTIME |
+                  SSH_FILEXFER_ATTR_BITS);
   switch(sb->st_mode & S_IFMT) {
-  case S_IFIFO: attrs->type = SSH_FILEXFER_TYPE_FIFO; break;
-  case S_IFCHR: attrs->type = SSH_FILEXFER_TYPE_CHAR_DEVICE; break;
-  case S_IFDIR: attrs->type = SSH_FILEXFER_TYPE_DIRECTORY; break;
-  case S_IFBLK: attrs->type = SSH_FILEXFER_TYPE_BLOCK_DEVICE; break;
-  case S_IFREG: attrs->type = SSH_FILEXFER_TYPE_REGULAR; break;
-  case S_IFLNK: attrs->type = SSH_FILEXFER_TYPE_SYMLINK; break;
-  case S_IFSOCK: attrs->type = SSH_FILEXFER_TYPE_SOCKET; break;
-  default: attrs->type = SSH_FILEXFER_TYPE_SPECIAL; break;
+  case S_IFIFO:
+    attrs->type = SSH_FILEXFER_TYPE_FIFO;
+    break;
+  case S_IFCHR:
+    attrs->type = SSH_FILEXFER_TYPE_CHAR_DEVICE;
+    break;
+  case S_IFDIR:
+    attrs->type = SSH_FILEXFER_TYPE_DIRECTORY;
+    break;
+  case S_IFBLK:
+    attrs->type = SSH_FILEXFER_TYPE_BLOCK_DEVICE;
+    break;
+  case S_IFREG:
+    attrs->type = SSH_FILEXFER_TYPE_REGULAR;
+    break;
+  case S_IFLNK:
+    attrs->type = SSH_FILEXFER_TYPE_SYMLINK;
+    break;
+  case S_IFSOCK:
+    attrs->type = SSH_FILEXFER_TYPE_SOCKET;
+    break;
+  default:
+    attrs->type = SSH_FILEXFER_TYPE_SPECIAL;
+    break;
   }
   attrs->size = sb->st_size;
   /* The cast ensures we don't do the multiply in a small word and overflow */
   attrs->allocation_size = (uint64_t)sb->st_blksize * sb->st_blocks;
   /* Only look up owner/group info if wanted */
-  if((flags & SSH_FILEXFER_ATTR_OWNERGROUP)
-     && (attrs->owner = sftp_uid2name(a, sb->st_uid))
-     && (attrs->group = sftp_gid2name(a, sb->st_gid)))
+  if((flags & SSH_FILEXFER_ATTR_OWNERGROUP) &&
+     (attrs->owner = sftp_uid2name(a, sb->st_uid)) &&
+     (attrs->group = sftp_gid2name(a, sb->st_gid)))
     attrs->valid |= SSH_FILEXFER_ATTR_OWNERGROUP;
   attrs->uid = sb->st_uid;
   attrs->gid = sb->st_gid;
@@ -77,12 +89,9 @@ void sftp_stat_to_attrs(struct allocator *a,
   attrs->mtime.seconds = sb->st_mtime;
   attrs->ctime.seconds = sb->st_ctime;
 #if HAVE_STAT_TIMESPEC
-  if(sb->st_atimespec.tv_nsec >= 0
-     && sb->st_atimespec.tv_nsec < 1000000000
-     && sb->st_mtimespec.tv_nsec >= 0
-     && sb->st_mtimespec.tv_nsec < 1000000000
-     && sb->st_ctimespec.tv_nsec >= 0
-     && sb->st_ctimespec.tv_nsec < 1000000000) {
+  if(sb->st_atimespec.tv_nsec >= 0 && sb->st_atimespec.tv_nsec < 1000000000 &&
+     sb->st_mtimespec.tv_nsec >= 0 && sb->st_mtimespec.tv_nsec < 1000000000 &&
+     sb->st_ctimespec.tv_nsec >= 0 && sb->st_ctimespec.tv_nsec < 1000000000) {
     /* Only send subsecond times if they are in range */
     attrs->atime.nanoseconds = sb->st_atimespec.tv_nsec;
     attrs->mtime.nanoseconds = sb->st_mtimespec.tv_nsec;
@@ -114,24 +123,21 @@ void sftp_stat_to_attrs(struct allocator *a,
 static const struct {
   uint32_t bit;
   const char *description;
-} attr_bits[] = {
-  { SSH_FILEXFER_ATTR_FLAGS_READONLY, "ro" },
-  { SSH_FILEXFER_ATTR_FLAGS_SYSTEM, "sys" },
-  { SSH_FILEXFER_ATTR_FLAGS_HIDDEN, "hide" },
-  { SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE, "ci"},
-  { SSH_FILEXFER_ATTR_FLAGS_ARCHIVE, "arc" },
-  { SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED, "enc" },
-  { SSH_FILEXFER_ATTR_FLAGS_COMPRESSED, "comp" },
-  { SSH_FILEXFER_ATTR_FLAGS_SPARSE, "sp" },
-  { SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY, "app" },
-  { SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE, "imm" },
-  { SSH_FILEXFER_ATTR_FLAGS_SYNC, "sync" },
-  { SSH_FILEXFER_ATTR_FLAGS_TRANSLATION_ERR, "trans" }
-};
-
-const char *sftp_format_attr(struct allocator *a,
-			const struct sftpattr *attrs, int thisyear,
-			unsigned long flags) {
+} attr_bits[] = {{SSH_FILEXFER_ATTR_FLAGS_READONLY, "ro"},
+                 {SSH_FILEXFER_ATTR_FLAGS_SYSTEM, "sys"},
+                 {SSH_FILEXFER_ATTR_FLAGS_HIDDEN, "hide"},
+                 {SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE, "ci"},
+                 {SSH_FILEXFER_ATTR_FLAGS_ARCHIVE, "arc"},
+                 {SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED, "enc"},
+                 {SSH_FILEXFER_ATTR_FLAGS_COMPRESSED, "comp"},
+                 {SSH_FILEXFER_ATTR_FLAGS_SPARSE, "sp"},
+                 {SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY, "app"},
+                 {SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE, "imm"},
+                 {SSH_FILEXFER_ATTR_FLAGS_SYNC, "sync"},
+                 {SSH_FILEXFER_ATTR_FLAGS_TRANSLATION_ERR, "trans"}};
+
+const char *sftp_format_attr(struct allocator *a, const struct sftpattr *attrs,
+                             int thisyear, unsigned long flags) {
   char perms[64], linkcount[64], size[64], date[64], nowner[64], ngroup[64];
   char *formatted, *p, *bits;
   size_t nbits;
@@ -146,44 +152,68 @@ const char *sftp_format_attr(struct allocator *a,
     *p++ = (attrs->permissions & 00400) ? 'r' : '-';
     *p++ = (attrs->permissions & 00200) ? 'w' : '-';
     switch(attrs->permissions & 04100) {
-    case 00000: *p++ = '-'; break;
-    case 00100: *p++ = 'x'; break;
-    case 04000: *p++ = 'S'; break;
-    case 04100: *p++ = 's'; break;
+    case 00000:
+      *p++ = '-';
+      break;
+    case 00100:
+      *p++ = 'x';
+      break;
+    case 04000:
+      *p++ = 'S';
+      break;
+    case 04100:
+      *p++ = 's';
+      break;
     }
     *p++ = (attrs->permissions & 00040) ? 'r' : '-';
     *p++ = (attrs->permissions & 00020) ? 'w' : '-';
     switch(attrs->permissions & 02010) {
-    case 00000: *p++ = '-'; break;
-    case 00010: *p++ = 'x'; break;
-    case 02000: *p++ = 'S'; break;
-    case 02010: *p++ = 's'; break;
+    case 00000:
+      *p++ = '-';
+      break;
+    case 00010:
+      *p++ = 'x';
+      break;
+    case 02000:
+      *p++ = 'S';
+      break;
+    case 02010:
+      *p++ = 's';
+      break;
     }
     *p++ = (attrs->permissions & 00004) ? 'r' : '-';
     *p++ = (attrs->permissions & 00002) ? 'w' : '-';
     switch(attrs->permissions & 01001) {
-    case 00000: *p++ = '-'; break;
-    case 00001: *p++ = 'x'; break;
-    case 01000: *p++ = 'T'; break;
-    case 01001: *p++ = 't'; break;
+    case 00000:
+      *p++ = '-';
+      break;
+    case 00001:
+      *p++ = 'x';
+      break;
+    case 01000:
+      *p++ = 'T';
+      break;
+    case 01001:
+      *p++ = 't';
+      break;
     }
     *p = 0;
   } else
     strcpy(p, "?????????");
   /* link count */
   if(attrs->valid & SSH_FILEXFER_ATTR_LINK_COUNT)
-    sprintf(linkcount, "%"PRIu32, attrs->link_count);
+    sprintf(linkcount, "%" PRIu32, attrs->link_count);
   else
     strcpy(linkcount, "?");
   /* size */
   if(attrs->valid & SSH_FILEXFER_ATTR_SIZE)
-    sprintf(size, "%"PRIu64, attrs->size);
+    sprintf(size, "%" PRIu64, attrs->size);
   else
     strcpy(size, "?");
   /* ownership */
   if(attrs->valid & SSH_FILEXFER_ATTR_UIDGID) {
-    sprintf(nowner, "%"PRIu32, attrs->uid);
-    sprintf(ngroup, "%"PRIu32, attrs->gid);
+    sprintf(nowner, "%" PRIu32, attrs->uid);
+    sprintf(ngroup, "%" PRIu32, attrs->gid);
   }
   owner = group = "?";
   if(flags & FORMAT_PREFER_NUMERIC_UID) {
@@ -219,41 +249,38 @@ const char *sftp_format_attr(struct allocator *a,
   /* attribute bits */
   bits = NULL;
   nbits = 0;
-  if(flags & FORMAT_ATTRS
-     && (attrs->valid & SSH_FILEXFER_ATTR_BITS)
-     && attrs->attrib_bits) {
-    bits = append(a, bits, &nbits, "[");
+  if(flags & FORMAT_ATTRS && (attrs->valid & SSH_FILEXFER_ATTR_BITS) &&
+     attrs->attrib_bits) {
+    bits = sftp_str_append(a, bits, &nbits, "[");
     for(n = 0; n < sizeof attr_bits / sizeof *attr_bits; ++n) {
       if(attrs->attrib_bits & attr_bits[n].bit) {
         if(bits[1])
-          bits = append(a, bits, &nbits, ",");
-        bits = append(a, bits, &nbits, attr_bits[n].description);
+          bits = sftp_str_append(a, bits, &nbits, ",");
+        bits = sftp_str_append(a, bits, &nbits, attr_bits[n].description);
       }
     }
-    bits = append(a, bits, &nbits, "]");
+    bits = sftp_str_append(a, bits, &nbits, "]");
   }
   /* Format the result */
   formatted = sftp_alloc(a, 80 + strlen(attrs->name));
 
   /* The draft is pretty specific about field widths */
   sprintf(formatted, "%10.10s %3.3s %-8.8s %-8.8s %8.8s %12.12s %s%s%s%s%s",
-	  perms, linkcount, owner, group,
-	  size, date, attrs->name,
-          attrs->target ? " -> " : "",
-          attrs->target ? attrs->target : "",
-          bits ? " " : "",
-          bits ? bits : "");
+          perms, linkcount, owner, group, size, date, attrs->name,
+          attrs->target ? " -> " : "", attrs->target ? attrs->target : "",
+          bits ? " " : "", bits ? bits : "");
   return formatted;
 }
 
-uint32_t sftp_normalize_ownergroup(struct allocator *a, struct sftpattr *attrs) {
+uint32_t sftp_normalize_ownergroup(struct allocator *a,
+                                   struct sftpattr *attrs) {
   uint32_t rc = SSH_FX_OK;
 
-  switch(attrs->valid & (SSH_FILEXFER_ATTR_UIDGID
-                         |SSH_FILEXFER_ATTR_OWNERGROUP)) {
+  switch(attrs->valid &
+         (SSH_FILEXFER_ATTR_UIDGID | SSH_FILEXFER_ATTR_OWNERGROUP)) {
   case SSH_FILEXFER_ATTR_UIDGID:
-    if((attrs->owner = sftp_uid2name(a, attrs->uid))
-       && (attrs->group = sftp_gid2name(a, attrs->gid)))
+    if((attrs->owner = sftp_uid2name(a, attrs->uid)) &&
+       (attrs->group = sftp_gid2name(a, attrs->gid)))
       attrs->valid |= SSH_FILEXFER_ATTR_OWNERGROUP;
     break;
   case SSH_FILEXFER_ATTR_OWNERGROUP:
@@ -310,16 +337,19 @@ struct sftp_set_status_callbacks {
 /* Horrendous ugliness for SETSTAT/FSETSTAT */
 #if HAVE_STAT_TIMESPEC
 /** @brief Helper macro to set fractional part of timestamps */
-#define SET_STATUS_NANOSEC do {                                         \
-    times[0].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_ACCESSTIME)    \
-                        ? (long)attrs.atime.nanoseconds                 \
-                        : current.st_atimespec.tv_nsec) / 1000;         \
-    times[1].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_MODIFYTIME)    \
-                        ? (long)attrs.mtime.nanoseconds                 \
-                        : current.st_mtimespec.tv_nsec) / 1000;         \
-} while(0)
+#  define SET_STATUS_NANOSEC                                                   \
+    do {                                                                       \
+      times[0].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_ACCESSTIME)         \
+                              ? (long)attrs.atime.nanoseconds                  \
+                              : current.st_atimespec.tv_nsec) /                \
+                         1000;                                                 \
+      times[1].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_MODIFYTIME)         \
+                              ? (long)attrs.mtime.nanoseconds                  \
+                              : current.st_mtimespec.tv_nsec) /                \
+                         1000;                                                 \
+    } while(0)
 #else
-#define SET_STATUS_NANOSEC ((void)0)
+#  define SET_STATUS_NANOSEC ((void)0)
 #endif
 
 /** @brief Implementation of sftp_set_status() and sftp_set_fstatus()
@@ -330,11 +360,10 @@ struct sftp_set_status_callbacks {
  * @param whyp Where to store error string, or a null pointer
  * @return 0 on success or an error code on failure
  */
-static uint32_t do_sftp_set_status(struct allocator *a,
-                              const void *what,
-                              const struct sftpattr *attrsp,
-                              const struct sftp_set_status_callbacks *cb,
-                              const char **whyp) {
+static uint32_t do_sftp_set_status(struct allocator *a, const void *what,
+                                   const struct sftpattr *attrsp,
+                                   const struct sftp_set_status_callbacks *cb,
+                                   const char **whyp) {
   struct timeval times[2];
   struct stat current;
   struct sftpattr attrs = *attrsp;
@@ -343,33 +372,31 @@ static uint32_t do_sftp_set_status(struct allocator *a,
   if(!whyp)
     whyp = &why;
   *whyp = 0;
-  if((attrs.valid & (SSH_FILEXFER_ATTR_SIZE|SSH_FILEXFER_ATTR_ALLOCATION_SIZE))
-     == (SSH_FILEXFER_ATTR_SIZE|SSH_FILEXFER_ATTR_ALLOCATION_SIZE)
-     && attrs.allocation_size < attrs.size) {
+  if((attrs.valid &
+      (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_ALLOCATION_SIZE)) ==
+         (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_ALLOCATION_SIZE) &&
+     attrs.allocation_size < attrs.size) {
     /* This is a MUST, e.g. draft -13 s7.4.  We honor it even though we don't
      * honor allocation-size. */
     *whyp = "size exceeds allocation-size";
     return SSH_FX_INVALID_PARAMETER;
   }
-  if(attrs.valid & (SSH_FILEXFER_ATTR_LINK_COUNT
-                    |SSH_FILEXFER_ATTR_TEXT_HINT))
+  if(attrs.valid & (SSH_FILEXFER_ATTR_LINK_COUNT | SSH_FILEXFER_ATTR_TEXT_HINT))
     /* Client has violated a MUST NOT */
     return SSH_FX_INVALID_PARAMETER;
-  if((attrs.valid & (SSH_FILEXFER_ATTR_SIZE
-                     |SSH_FILEXFER_ATTR_PERMISSIONS
-                     |SSH_FILEXFER_ATTR_ACCESSTIME
-                     |SSH_FILEXFER_ATTR_MODIFYTIME
-                     |SSH_FILEXFER_ATTR_UIDGID
-                     |SSH_FILEXFER_ATTR_OWNERGROUP
-                     |SSH_FILEXFER_ATTR_SUBSECOND_TIMES
-                     |SSH_FILEXFER_ATTR_ALLOCATION_SIZE)) != attrs.valid) {
+  if((attrs.valid &
+      (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+       SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+       SSH_FILEXFER_ATTR_UIDGID | SSH_FILEXFER_ATTR_OWNERGROUP |
+       SSH_FILEXFER_ATTR_SUBSECOND_TIMES |
+       SSH_FILEXFER_ATTR_ALLOCATION_SIZE)) != attrs.valid) {
     /* SHOULD not change any attributes if we cannot perform as required.  We
      * have a SHOULD which allows us to ignore allocation-size. */
     *whyp = "unsupported flags";
     return SSH_FX_OP_UNSUPPORTED;
   }
   if(attrs.valid & SSH_FILEXFER_ATTR_SIZE) {
-    D(("...truncate to %"PRIu64, attrs.size));
+    D(("...truncate to %" PRIu64, attrs.size));
     if(cb->do_truncate(what, attrs.size) < 0) {
       *whyp = "truncate";
       return HANDLER_ERRNO;
@@ -377,7 +404,7 @@ static uint32_t do_sftp_set_status(struct allocator *a,
   }
   sftp_normalize_ownergroup(a, &attrs);
   if(attrs.valid & SSH_FILEXFER_ATTR_UIDGID) {
-    D(("...chown to %"PRId32"/%"PRId32, attrs.uid, attrs.gid));
+    D(("...chown to %" PRId32 "/%" PRId32, attrs.uid, attrs.gid));
     if(cb->do_chown(what, attrs.uid, attrs.gid) < 0) {
       *whyp = "chown";
       return HANDLER_ERRNO;
@@ -391,35 +418,35 @@ static uint32_t do_sftp_set_status(struct allocator *a,
       return HANDLER_ERRNO;
     }
   }
-  if(attrs.valid & (SSH_FILEXFER_ATTR_ACCESSTIME
-                     |SSH_FILEXFER_ATTR_MODIFYTIME)) {
+  if(attrs.valid &
+     (SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME)) {
     if(cb->do_stat(what, &current) < 0) {
       D(("cannot stat"));
       *whyp = "stat";
       return HANDLER_ERRNO;
     }
-    memset(times, 0, sizeof times);
+    sftp_memset(times, 0, sizeof times);
     times[0].tv_sec = ((attrs.valid & SSH_FILEXFER_ATTR_ACCESSTIME)
-                       ? (time_t)attrs.atime.seconds
-                       : current.st_atime);
+                           ? (time_t)attrs.atime.seconds
+                           : current.st_atime);
     times[1].tv_sec = ((attrs.valid & SSH_FILEXFER_ATTR_MODIFYTIME)
-                       ? (time_t)attrs.mtime.seconds
-                       : current.st_mtime);
+                           ? (time_t)attrs.mtime.seconds
+                           : current.st_mtime);
 #if HAVE_STAT_TIMESPEC
     if(attrs.valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) {
       times[0].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_ACCESSTIME)
-                          ? (long)attrs.atime.nanoseconds
-                          : current.st_atimespec.tv_nsec) / 1000;
+                              ? (long)attrs.atime.nanoseconds
+                              : current.st_atimespec.tv_nsec) /
+                         1000;
       times[1].tv_usec = ((attrs.valid & SSH_FILEXFER_ATTR_MODIFYTIME)
-                          ? (long)attrs.mtime.nanoseconds
-                          : current.st_mtimespec.tv_nsec) / 1000;
+                              ? (long)attrs.mtime.nanoseconds
+                              : current.st_mtimespec.tv_nsec) /
+                         1000;
     }
 #endif
     D(("...utimes to atime %lu.%06lu mtime %lu.%06lu",
-       (unsigned long)times[0].tv_sec,
-       (unsigned long)times[0].tv_usec,
-       (unsigned long)times[1].tv_sec,
-       (unsigned long)times[1].tv_usec));
+       (unsigned long)times[0].tv_sec, (unsigned long)times[0].tv_usec,
+       (unsigned long)times[1].tv_sec, (unsigned long)times[1].tv_usec));
     if(cb->do_utimes(what, times) < 0) {
       *whyp = "utimes";
       return HANDLER_ERRNO;
@@ -476,17 +503,10 @@ static int name_utimes(const void *what, struct timeval *tv) {
 
 /** @brief Table of callbacks for sftp_set_status() */
 static const struct sftp_set_status_callbacks name_callbacks = {
-  name_truncate,
-  name_chown,
-  name_chmod,
-  name_lstat,
-  name_utimes
-};
+    name_truncate, name_chown, name_chmod, name_lstat, name_utimes};
 
-uint32_t sftp_set_status(struct allocator *a,
-                    const char *path,
-                    const struct sftpattr *attrsp,
-                    const char **whyp) {
+uint32_t sftp_set_status(struct allocator *a, const char *path,
+                         const struct sftpattr *attrsp, const char **whyp) {
   return do_sftp_set_status(a, path, attrsp, &name_callbacks, whyp);
 }
 
@@ -538,17 +558,10 @@ static int fd_utimes(const void *what, struct timeval *tv) {
 
 /** @brief Table of callbacks for sftp_set_fstatus() */
 static const struct sftp_set_status_callbacks fd_callbacks = {
-  fd_truncate,
-  fd_chown,
-  fd_chmod,
-  fd_stat,
-  fd_utimes
-};
+    fd_truncate, fd_chown, fd_chmod, fd_stat, fd_utimes};
 
-uint32_t sftp_set_fstatus(struct allocator *a,
-                     int fd,
-                     const struct sftpattr *attrsp,
-                     const char **whyp) {
+uint32_t sftp_set_fstatus(struct allocator *a, int fd,
+                          const struct sftpattr *attrsp, const char **whyp) {
   return do_sftp_set_status(a, &fd, attrsp, &fd_callbacks, whyp);
 }
 
diff --git a/stat.h b/stat.h
index cb9e1ec..c89969e 100644
--- a/stat.h
+++ b/stat.h
@@ -21,7 +21,7 @@
 /** @file stat.h @brief SFTP attribute support interface */
 
 #ifndef STAT_H
-#define STAT_H
+#  define STAT_H
 
 /** @brief Produce a human-readable representation of file attributes
  * @param a Allocator
@@ -35,37 +35,35 @@
  * - @ref FORMAT_PREFER_LOCALTIME
  * - @ref FORMAT_ATTRS
  */
-const char *sftp_format_attr(struct allocator *a,
-                             const struct sftpattr *attrs, int thisyear,
-                             unsigned long flags);
+const char *sftp_format_attr(struct allocator *a, const struct sftpattr *attrs,
+                             int thisyear, unsigned long flags);
 /** @brief User numeric instead of named user and group IDs
  *
  * See sftp_format_attr().
  */
-#define FORMAT_PREFER_NUMERIC_UID 0x00000001
+#  define FORMAT_PREFER_NUMERIC_UID 0x00000001
 
 /** @brief Use local time instead of UTC
  *
  * See sftp_format_attr().
  */
-#define FORMAT_PREFER_LOCALTIME 0x00000002
+#  define FORMAT_PREFER_LOCALTIME 0x00000002
 
 /** @brief Include attribute bits
  *
  * See sftp_format_attr().
  */
-#define FORMAT_ATTRS 0x00000004
+#  define FORMAT_ATTRS 0x00000004
 
 /** @brief Fill in missing owner/group attributes
  * @param a Allocator
  * @param attrs Attributes
- * @return 0 on success, status code on error 
+ * @return 0 on success, status code on error
  *
  * If exactly one of @ref SSH_FILEXFER_ATTR_UIDGID and @ref
  * SSH_FILEXFER_ATTR_OWNERGROUP is present then attempt to fill in the other.
  */
-uint32_t sftp_normalize_ownergroup(struct allocator *a,
-                                   struct sftpattr *attrs);
+uint32_t sftp_normalize_ownergroup(struct allocator *a, struct sftpattr *attrs);
 
 /** @brief Set the attributes on a path name
  * @param a Allocator
@@ -74,10 +72,8 @@ uint32_t sftp_normalize_ownergroup(struct allocator *a,
  * @param whyp Where to store error string, or a null pointer
  * @return 0 on success or an error code on failure
  */
-uint32_t sftp_set_status(struct allocator *a,
-                         const char *path,
-                         const struct sftpattr *attrs,
-                         const char **whyp);
+uint32_t sftp_set_status(struct allocator *a, const char *path,
+                         const struct sftpattr *attrs, const char **whyp);
 
 /** @brief Set the attributes on an open file
  * @param a Allocator
@@ -86,10 +82,8 @@ uint32_t sftp_set_status(struct allocator *a,
  * @param whyp Where to store error string, or a null pointer
  * @return 0 on success or an error code on failure
  */
-uint32_t sftp_set_fstatus(struct allocator *a,
-                          int fd,
-                          const struct sftpattr *attrs,
-                          const char **whyp);
+uint32_t sftp_set_fstatus(struct allocator *a, int fd,
+                          const struct sftpattr *attrs, const char **whyp);
 
 /** @brief Convert @c stat() output to SFTP attributes
  * @param a Allocator
@@ -103,12 +97,12 @@ uint32_t sftp_set_fstatus(struct allocator *a,
  * filled in.
  *
  * @todo @ref SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE is not implemented.
- * 
+ *
  * @todo @ref SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE is not implemented.
  */
-void sftp_stat_to_attrs(struct allocator *a,
-                        const struct stat *sb, struct sftpattr *attrs,
-                        uint32_t flags, const char *path);
+void sftp_stat_to_attrs(struct allocator *a, const struct stat *sb,
+                        struct sftpattr *attrs, uint32_t flags,
+                        const char *path);
 
 #endif /* STAT_H */
 
diff --git a/status.c b/status.c
index b3e9d5c..0e2af32 100644
--- a/status.c
+++ b/status.c
@@ -31,45 +31,76 @@
 
 const char *status_to_string(uint32_t status) {
   switch(status) {
-  case SSH_FX_OK: return "OK";
-  case SSH_FX_EOF: return "end of file";
-  case SSH_FX_NO_SUCH_FILE: return "file does not exist";
-  case SSH_FX_PERMISSION_DENIED: return "permission denied";
-  case SSH_FX_FAILURE: return "operation failed";
-  case SSH_FX_BAD_MESSAGE: return "badly encoded SFTP packet";
-  case SSH_FX_NO_CONNECTION: return "no connection";
-  case SSH_FX_CONNECTION_LOST: return "connection lost";
-  case SSH_FX_OP_UNSUPPORTED: return "operation not supported";
-  case SSH_FX_INVALID_HANDLE: return "invalid handle";
-  case SSH_FX_NO_SUCH_PATH: return "path does not exist or is invalid";
-  case SSH_FX_FILE_ALREADY_EXISTS: return "file already exists";
-  case SSH_FX_WRITE_PROTECT: return "file is on read-only medium";
-  case SSH_FX_NO_MEDIA: return "no medium in drive";
-  case SSH_FX_NO_SPACE_ON_FILESYSTEM: return "no space on filesystem";
-  case SSH_FX_QUOTA_EXCEEDED: return "quota exceeded";
-  case SSH_FX_UNKNOWN_PRINCIPAL: return "unknown principal";
-  case SSH_FX_LOCK_CONFLICT: return "file is locked";
-  case SSH_FX_DIR_NOT_EMPTY: return "directory is not empty";
-  case SSH_FX_NOT_A_DIRECTORY: return "file is not a directory";
-  case SSH_FX_INVALID_FILENAME: return "invalid filename";
-  case SSH_FX_LINK_LOOP: return "too many symbolic links";
-  case SSH_FX_CANNOT_DELETE: return "file cannot be deleted";
-  case SSH_FX_INVALID_PARAMETER: return "invalid parameter";
-  case SSH_FX_FILE_IS_A_DIRECTORY: return "file is a directory";
-  case SSH_FX_BYTE_RANGE_LOCK_CONFLICT: return "byte range is locked";
-  case SSH_FX_BYTE_RANGE_LOCK_REFUSED: return "cannot lock byte range";
-  case SSH_FX_DELETE_PENDING: return "file deletion pending";
-  case SSH_FX_FILE_CORRUPT: return "file is corrupt";
-  case SSH_FX_OWNER_INVALID: return "invalid owner";
-  case SSH_FX_GROUP_INVALID: return "invalid group";
-  case SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK: return "no such lock";
-  default: return "unknown status";
+  case SSH_FX_OK:
+    return "OK";
+  case SSH_FX_EOF:
+    return "end of file";
+  case SSH_FX_NO_SUCH_FILE:
+    return "file does not exist";
+  case SSH_FX_PERMISSION_DENIED:
+    return "permission denied";
+  case SSH_FX_FAILURE:
+    return "operation failed";
+  case SSH_FX_BAD_MESSAGE:
+    return "badly encoded SFTP packet";
+  case SSH_FX_NO_CONNECTION:
+    return "no connection";
+  case SSH_FX_CONNECTION_LOST:
+    return "connection lost";
+  case SSH_FX_OP_UNSUPPORTED:
+    return "operation not supported";
+  case SSH_FX_INVALID_HANDLE:
+    return "invalid handle";
+  case SSH_FX_NO_SUCH_PATH:
+    return "path does not exist or is invalid";
+  case SSH_FX_FILE_ALREADY_EXISTS:
+    return "file already exists";
+  case SSH_FX_WRITE_PROTECT:
+    return "file is on read-only medium";
+  case SSH_FX_NO_MEDIA:
+    return "no medium in drive";
+  case SSH_FX_NO_SPACE_ON_FILESYSTEM:
+    return "no space on filesystem";
+  case SSH_FX_QUOTA_EXCEEDED:
+    return "quota exceeded";
+  case SSH_FX_UNKNOWN_PRINCIPAL:
+    return "unknown principal";
+  case SSH_FX_LOCK_CONFLICT:
+    return "file is locked";
+  case SSH_FX_DIR_NOT_EMPTY:
+    return "directory is not empty";
+  case SSH_FX_NOT_A_DIRECTORY:
+    return "file is not a directory";
+  case SSH_FX_INVALID_FILENAME:
+    return "invalid filename";
+  case SSH_FX_LINK_LOOP:
+    return "too many symbolic links";
+  case SSH_FX_CANNOT_DELETE:
+    return "file cannot be deleted";
+  case SSH_FX_INVALID_PARAMETER:
+    return "invalid parameter";
+  case SSH_FX_FILE_IS_A_DIRECTORY:
+    return "file is a directory";
+  case SSH_FX_BYTE_RANGE_LOCK_CONFLICT:
+    return "byte range is locked";
+  case SSH_FX_BYTE_RANGE_LOCK_REFUSED:
+    return "cannot lock byte range";
+  case SSH_FX_DELETE_PENDING:
+    return "file deletion pending";
+  case SSH_FX_FILE_CORRUPT:
+    return "file is corrupt";
+  case SSH_FX_OWNER_INVALID:
+    return "invalid owner";
+  case SSH_FX_GROUP_INVALID:
+    return "invalid group";
+  case SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK:
+    return "no such lock";
+  default:
+    return "unknown status";
   }
 }
 
-void sftp_send_status(struct sftpjob *job, 
-                 uint32_t status,
-                 const char *msg) {
+void sftp_send_status(struct sftpjob *job, uint32_t status, const char *msg) {
   if(status == HANDLER_ERRNO) {
     /* Bodge to allow us to treat -1 as a magical status meaning 'consult
      * errno'.  This goes back via the protocol-specific status callback, so
@@ -84,16 +115,22 @@ void sftp_send_status(struct sftpjob *job,
   /* Limit to status values known to this version of the protocol */
   if(status > protocol->maxstatus) {
     switch(status) {
-    case SSH_FX_INVALID_FILENAME: status = SSH_FX_BAD_MESSAGE; break;
-    case SSH_FX_NO_SUCH_PATH: status = SSH_FX_NO_SUCH_FILE; break;
-    default: status = SSH_FX_FAILURE; break;
+    case SSH_FX_INVALID_FILENAME:
+      status = SSH_FX_BAD_MESSAGE;
+      break;
+    case SSH_FX_NO_SUCH_PATH:
+      status = SSH_FX_NO_SUCH_FILE;
+      break;
+    default:
+      status = SSH_FX_FAILURE;
+      break;
     }
   }
   sftp_send_begin(job->worker);
   sftp_send_uint8(job->worker, SSH_FXP_STATUS);
   sftp_send_uint32(job->worker, job->id);
   sftp_send_uint32(job->worker, status);
-  sftp_send_path(job, job->worker, msg);     /* needs to be UTF-8 */
+  sftp_send_path(job, job->worker, msg); /* needs to be UTF-8 */
   /* We are not I18N'd yet.  Doing so will require the following:
    *  - determine an RFC1766 interpretation of the current LC_MESSAGES
    *    setting
@@ -111,28 +148,28 @@ static const struct {
   int errno_value;
   uint32_t status_value;
 } errnotab[] = {
-  { 0, SSH_FX_OK },
-  { EPERM, SSH_FX_PERMISSION_DENIED },
-  { EACCES, SSH_FX_PERMISSION_DENIED },
-  { ENOENT, SSH_FX_NO_SUCH_FILE },
-  { EIO, SSH_FX_FILE_CORRUPT },
-  { ENOSPC, SSH_FX_NO_SPACE_ON_FILESYSTEM },
-  { ENOTDIR, SSH_FX_NOT_A_DIRECTORY },
-  { EISDIR, SSH_FX_FILE_IS_A_DIRECTORY },
-  { EEXIST, SSH_FX_FILE_ALREADY_EXISTS },
-  { EROFS, SSH_FX_WRITE_PROTECT },
-  { ELOOP, SSH_FX_LINK_LOOP },
-  { ENAMETOOLONG, SSH_FX_INVALID_FILENAME },
-  { ENOTEMPTY, SSH_FX_DIR_NOT_EMPTY },
-  { EDQUOT, SSH_FX_QUOTA_EXCEEDED },
-  { -1, SSH_FX_FAILURE },
+    {0, SSH_FX_OK},
+    {EPERM, SSH_FX_PERMISSION_DENIED},
+    {EACCES, SSH_FX_PERMISSION_DENIED},
+    {ENOENT, SSH_FX_NO_SUCH_FILE},
+    {EIO, SSH_FX_FILE_CORRUPT},
+    {ENOSPC, SSH_FX_NO_SPACE_ON_FILESYSTEM},
+    {ENOTDIR, SSH_FX_NOT_A_DIRECTORY},
+    {EISDIR, SSH_FX_FILE_IS_A_DIRECTORY},
+    {EEXIST, SSH_FX_FILE_ALREADY_EXISTS},
+    {EROFS, SSH_FX_WRITE_PROTECT},
+    {ELOOP, SSH_FX_LINK_LOOP},
+    {ENAMETOOLONG, SSH_FX_INVALID_FILENAME},
+    {ENOTEMPTY, SSH_FX_DIR_NOT_EMPTY},
+    {EDQUOT, SSH_FX_QUOTA_EXCEEDED},
+    {-1, SSH_FX_FAILURE},
 };
 
 void sftp_send_errno_status(struct sftpjob *job) {
   int n;
   const int errno_value = errno;
 
-  for(n = 0; 
+  for(n = 0;
       errnotab[n].errno_value != errno_value && errnotab[n].errno_value != -1;
       ++n)
     ;
diff --git a/thread.h b/thread.h
index 62d7563..0495c7d 100644
--- a/thread.h
+++ b/thread.h
@@ -21,24 +21,24 @@
 /** @file thread.h @brief Thread utilities */
 
 #ifndef THREAD_H
-#define THREAD_H
+#  define THREAD_H
 
-#include <pthread.h>
-#include <stdio.h>
+#  include <pthread.h>
+#  include <stdio.h>
 
-#if NTHREADS > 1 || CLIENT
+#  if NTHREADS > 1 || CLIENT
 /** @brief Error-checking macro for @c pthread_... functions */
-#define ferrcheck(E) do {                                       \
-  const int frc = (E);                                          \
-  if(frc) {                                                     \
-    fatal("%s:%d: %s: %s\n", __FILE__, __LINE__,                \
-          #E, strerror(frc));                                   \
-    exit(1);                                                    \
-  }                                                             \
-} while(0)
-#else
-#define ferrcheck(E) (void)0
-#endif
+#    define ferrcheck(E)                                                       \
+      do {                                                                     \
+        const int frc = (E);                                                   \
+        if(frc) {                                                              \
+          sftp_fatal("%s:%d: %s: %s\n", __FILE__, __LINE__, #E, strerror(frc));     \
+          exit(1);                                                             \
+        }                                                                      \
+      } while(0)
+#  else
+#    define ferrcheck(E) (void)0
+#  endif
 
 #endif /* THREAD_H */
 
diff --git a/types.h b/types.h
index 3b8b96f..931f541 100644
--- a/types.h
+++ b/types.h
@@ -21,11 +21,11 @@
 /** @file types.h @brief Data types */
 
 #ifndef TYPES_H
-#define TYPES_H
+#  define TYPES_H
 
-#include <sys/stat.h>
-#include <wchar.h>
-#include <iconv.h>
+#  include <sys/stat.h>
+#  include <wchar.h>
+#  include <iconv.h>
 
 /** @brief An SFTP timestamp */
 struct sftptime {
@@ -243,7 +243,7 @@ struct sftpjob {
   uint32_t id;
 
   /** @brief Worker processing this job */
-  struct worker *worker;                /* worker processing this job */
+  struct worker *worker; /* worker processing this job */
 };
 
 /** @brief An SFTP request */
@@ -268,10 +268,10 @@ struct sftpextension {
 };
 
 /** @brief Internal error code meaning "already responded" */
-#define HANDLER_RESPONDED ((uint32_t)-1)
+#  define HANDLER_RESPONDED ((uint32_t)-1)
 
 /** @brief Internal error code meaning "consult errno" */
-#define HANDLER_ERRNO ((uint32_t)-2)
+#  define HANDLER_ERRNO ((uint32_t)-2)
 
 /** @brief Definition of an SFTP protocol version */
 struct sftpprotocol {
@@ -298,8 +298,8 @@ struct sftpprotocol {
    * @param names Filenames (and attributes) to send
    * @return Error code
    */
-  void (*sendnames)(struct sftpjob *job, 
-                    int nnames, const struct sftpattr *names);
+  void (*sendnames)(struct sftpjob *job, int nnames,
+                    const struct sftpattr *names);
 
   /** @brief Send file attributes
    * @param job Job
@@ -320,16 +320,14 @@ struct sftpprotocol {
    * @param path Input/output filename
    * @return 0 on success, -1 on error (as per sftp_iconv())
    */
-  int (*encode)(struct sftpjob *job,
-                char **path);
+  int (*encode)(struct sftpjob *job, char **path);
 
   /** @brief Decode a filename
    * @param job Job
    * @param path Input/output filename
    * @return Error code
    */
-  uint32_t (*decode)(struct sftpjob *job,
-                     char **path);
+  uint32_t (*decode)(struct sftpjob *job, char **path);
 
   /** @brief Number of extension types supported */
   int nextensions;
diff --git a/users.h b/users.h
index 71e7fbe..3b28d84 100644
--- a/users.h
+++ b/users.h
@@ -19,9 +19,9 @@
  */
 
 #ifndef USERS_H
-#define USERS_H
+#  define USERS_H
 
-#include <sys/types.h>
+#  include <sys/types.h>
 
 struct allocator;
 
diff --git a/utils.c b/utils.c
index 78322ce..45dc9ec 100644
--- a/utils.c
+++ b/utils.c
@@ -32,9 +32,9 @@
 #include <limits.h>
 #include <assert.h>
 
-int log_syslog;
+int sftp_log_syslog;
 
-int do_read(int fd, void *buffer, size_t size) {
+int sftp_xread(int fd, void *buffer, size_t size) {
   size_t sofar = 0;
   ssize_t n;
   char *ptr = buffer;
@@ -44,42 +44,42 @@ int do_read(int fd, void *buffer, size_t size) {
     if(n > 0)
       sofar += n;
     else if(n == 0)
-      return -1;                        /* eof */
+      return -1; /* eof */
     else
-      fatal("read error: %s", strerror(errno));
+      sftp_fatal("read error: %s", strerror(errno));
   }
-  return 0;                             /* ok */
+  return 0; /* ok */
 }
 
-void *xmalloc(size_t n) {
+void *sftp_xmalloc(size_t n) {
   void *ptr;
 
-  if(n) {
-    if(!(ptr = malloc(n)))
-      fatal("xmalloc: out of memory (%zu)", n);
-    return ptr;
-  } else
-    return 0;
+  if(!n)
+    n = 1;
+  if(!(ptr = malloc(n)))
+    sftp_fatal("sftp_xmalloc: out of memory (%zu)", n);
+  return ptr;
 }
 
-void *xcalloc(size_t n, size_t size) {
+void *sftp_xcalloc(size_t n, size_t size) {
   void *ptr;
 
-  if(n && size) {
-    if(!(ptr = calloc(n, size)))
-      fatal("xcalloc: out of memory (%zu, %zu)", n, size);
-    return ptr;
-  } else
-    return 0;
+  if(!n)
+    n = 1;
+  if(!size)
+    size = 1;
+  if(!(ptr = calloc(n, size)))
+    sftp_fatal("sftp_xcalloc: out of memory (%zu, %zu)", n, size);
+  return ptr;
 }
 
-void *xrecalloc(void *ptr, size_t n, size_t size) {
+void *sftp_xrecalloc(void *ptr, size_t n, size_t size) {
   if(n > SIZE_MAX / size)
-    fatal("xrecalloc: out of memory (%zu, %zu)", n, size);
+    sftp_fatal("sftp_xrecalloc: out of memory (%zu, %zu)", n, size);
   n *= size;
   if(n) {
     if(!(ptr = realloc(ptr, n)))
-      fatal("xrecalloc: out of memory (%zu)", n);
+      sftp_fatal("sftp_xrecalloc: out of memory (%zu)", n);
     return ptr;
   } else {
     free(ptr);
@@ -87,10 +87,10 @@ void *xrecalloc(void *ptr, size_t n, size_t size) {
   }
 }
 
-void *xrealloc(void *ptr, size_t n) {
+void *sftp_xrealloc(void *ptr, size_t n) {
   if(n) {
     if(!(ptr = realloc(ptr, n)))
-      fatal("xrealloc: out of memory (%zu)", n);
+      sftp_fatal("sftp_xrealloc: out of memory (%zu)", n);
     return ptr;
   } else {
     free(ptr);
@@ -98,17 +98,17 @@ void *xrealloc(void *ptr, size_t n) {
   }
 }
 
-char *xstrdup(const char *s) {
-  return strcpy(xmalloc(strlen(s) + 1), s);
+char *sftp_xstrdup(const char *s) {
+  return strcpy(sftp_xmalloc(strlen(s) + 1), s);
 }
 
 static void (*exitfn)(int) attribute((noreturn)) = exit;
 
-void fatal(const char *msg, ...) {
+void sftp_fatal(const char *msg, ...) {
   va_list ap;
 
   va_start(ap, msg);
-  if(log_syslog)
+  if(sftp_log_syslog)
     vsyslog(LOG_ERR, msg, ap);
   else {
     fprintf(stderr, "FATAL: ");
@@ -119,31 +119,29 @@ void fatal(const char *msg, ...) {
   exitfn(-1);
 }
 
-void forked(void) {
-  exitfn = _exit;
-}
+void sftp_forked(void) { exitfn = _exit; }
 
-pid_t xfork(void) {
+pid_t sftp_xfork(void) {
   pid_t pid;
 
   if((pid = fork()) < 0)
-    fatal("fork: %s", strerror(errno));
+    sftp_fatal("fork: %s", strerror(errno));
   if(!pid)
-    forked();
+    sftp_forked();
   return pid;
 }
 
-char *appendn(struct allocator *a, char *s, size_t *ns,
-              const char *t, size_t lt) {
+char *sftp_str_appendn(struct allocator *a, char *s, size_t *ns, const char *t,
+                       size_t lt) {
   const size_t ls = s ? strlen(s) : 0, need = lt + ls + 1;
-  
+
   if(need > *ns) {
     size_t newsize = *ns ? *ns : 16;
 
     while(need > newsize && newsize)
       newsize *= 2;
     if(!newsize)
-      fatal("appendn: out of memory (%zu, %zu)", ls, need);
+      sftp_fatal("sftp_str_appendn: out of memory (%zu, %zu)", ls, need);
     s = sftp_alloc_more(a, s, *ns, newsize);
     *ns = newsize;
   } else {
@@ -151,14 +149,13 @@ char *appendn(struct allocator *a, char *s, size_t *ns,
     assert(s);
   }
 
-  memcpy(s + ls, t, lt);
+  sftp_memcpy(s + ls, t, lt);
   s[ls + lt] = 0;
   return s;
 }
 
-char *append(struct allocator *a, char *s, size_t *ns, 
-             const char *t) {
-  return appendn(a, s, ns, t, strlen(t));
+char *sftp_str_append(struct allocator *a, char *s, size_t *ns, const char *t) {
+  return sftp_str_appendn(a, s, ns, t, strlen(t));
 }
 
 /*
diff --git a/utils.h b/utils.h
index 5787e2f..4a13dcc 100644
--- a/utils.h
+++ b/utils.h
@@ -21,8 +21,10 @@
 /** @file utils.h @brief Utility functions interface */
 
 #ifndef UTILS_H
-#define UTILS_H
+#  define UTILS_H
 
+#  include <string.h>
+#  include <assert.h>
 
 /** @brief Read bytes from @p fd
  * @param fd File descriptor to read from
@@ -30,44 +32,39 @@
  * @param size Number of bytes to read
  * @return 0 on success, non-0 if EOF before @p size bytes read
  *
- * Loops if necessary to cope with short reads.  Calls fatal() on error.
+ * Loops if necessary to cope with short reads.  Calls sftp_fatal() on error.
  */
-int do_read(int fd, void *buffer, size_t size);
-
-/* libreadliine contains xmalloc/xrealloc!  We use some #defines to work around
- * the problem. */
-#define xmalloc sftp__xmalloc
-#define xrealloc sftp__xrealloc
+int sftp_xread(int fd, void *buffer, size_t size);
 
 /** @brief Allocate memory
  * @param n Number of bytes to allocate
  * @return Pointer to allocated memory
  *
- * Equivalent to @c malloc() but calls fatal() on error.
+ * Equivalent to @c malloc() but calls sftp_fatal() on error.
  *
  * Does not zero-fill.
  */
-void *xmalloc(size_t n);
+void *sftp_xmalloc(size_t n);
 
 /** @brief Allocate memory
  * @param n Number of objects to allocate
  * @param size Size of one object
  * @return Pointer to allocated memory
  *
- * Equivalent to @c calloc() but calls fatal() on error.
+ * Equivalent to @c calloc() but calls sftp_fatal() on error.
  */
-void *xcalloc(size_t n, size_t size);
+void *sftp_xcalloc(size_t n, size_t size);
 
 /** @brief Reallocate memory
  * @param ptr Existing allocation
  * @param n Number of bytes to allocate
  * @return Pointer to allocated memory
  *
- * Equivalent to @c realloc() but calls fatal() on error.
+ * Equivalent to @c realloc() but calls sftp_fatal() on error.
  *
  * Does not zero-fill.
  */
-void *xrealloc(void *ptr, size_t n);
+void *sftp_xrealloc(void *ptr, size_t n);
 
 /** @brief Reallocate memory
  * @param ptr Existing allocation
@@ -75,19 +72,19 @@ void *xrealloc(void *ptr, size_t n);
  * @param size Size of one object
  * @return Pointer to allocated memory
  *
- * Equivalent to @c realloc() but calls fatal() on error.
+ * Equivalent to @c realloc() but calls sftp_fatal() on error.
  *
  * Does not zero-fill.
  */
-void *xrecalloc(void *ptr, size_t n, size_t size);
+void *sftp_xrecalloc(void *ptr, size_t n, size_t size);
 
 /** @brief Duplicate a string
  * @param s String to duplicate
  * @return Duplicated string
  *
- * Equivalent to @c strdup() but calls fatal() on error.
+ * Equivalent to @c strdup() but calls sftp_fatal() on error.
  */
-char *xstrdup(const char *s);
+char *sftp_xstrdup(const char *s);
 
 /** @brief Append to a string
  * @param a Allocator
@@ -96,8 +93,7 @@ char *xstrdup(const char *s);
  * @param t String to append
  * @return New string
  */
-char *append(struct allocator *a, char *s, size_t *ns, 
-             const char *t);
+char *sftp_str_append(struct allocator *a, char *s, size_t *ns, const char *t);
 
 /** @brief Append to a string
  * @param a Allocator
@@ -107,8 +103,8 @@ char *append(struct allocator *a, char *s, size_t *ns,
  * @param lt Length of @p t
  * @return New string
  */
-char *appendn(struct allocator *a, char *s, size_t *ns, 
-              const char *t, size_t lt);
+char *sftp_str_appendn(struct allocator *a, char *s, size_t *ns, const char *t,
+                       size_t lt);
 
 /** @brief Convenient wrapper for readlink(2)
  * @param a Allocator to store result
@@ -145,20 +141,19 @@ char *sftp_do_readlink(struct allocator *a, const char *path);
  *
  * Sets @c errno on erorr.
  */
-char *sftp_find_realpath(struct allocator *a, const char *path,
-                         unsigned flags);
+char *sftp_find_realpath(struct allocator *a, const char *path, unsigned flags);
 
 /** @brief Follow symlinks
  *
  * See sftp_find_realpath().
  */
-#define RP_READLINK 0x0001
+#  define RP_READLINK 0x0001
 
 /** @brief Path must exist
  *
  * See sftp_find_realpath().
  */
-#define RP_MUST_EXIST 0x0002
+#  define RP_MUST_EXIST 0x0002
 
 /** @brief Compute the name of the current directory
  * @param a Allocator to store result
@@ -178,35 +173,62 @@ const char *sftp_dirname(struct allocator *a, const char *path);
  * @param ... Arguments
  *
  * The error is written either to standard error or syslog; see @ref
- * log_syslog.
+ * sftp_log_syslog.
  *
  * Terminates the process.
  */
-void fatal(const char *msg, ...)
-  attribute((noreturn))
-  attribute((format(printf,1,2)));
+void sftp_fatal(const char *msg, ...) attribute((noreturn))
+    attribute((format(printf, 1, 2)));
 
 /** @brief Fork a subprocess
  * @return 0 in the child, process ID in the parent
  *
- * Calls fatal() on error.
+ * Calls sftp_fatal() on error.
  */
-pid_t xfork(void);
+pid_t sftp_xfork(void);
 
 /** @brief Called after forking
  *
- * Affects the way that fatal() terminates the process.
+ * Affects the way that sftp_fatal() terminates the process.
  *
- * xfork() already calls it, any other calls to @c fork() should call it
+ * sftp_xfork() already calls it, any other calls to @c fork() should call it
  * explicitly.
  */
-void forked(void);
+void sftp_forked(void);
+
+/** @brief memcpy wrapper
+ *
+ * Equivalent to @c memcpy except that the prohibition on null pointer
+ * arguments is removed when @p n is 0.
+ */
+static inline void *sftp_memcpy(void *restrict dest, const void *restrict src,
+                                size_t n) {
+  if(n) {
+    assert(dest);
+    assert(src);
+    return memcpy(dest, src, n);
+  }
+  return dest;
+}
+
+/** @brief sftp_memset wrapper
+ *
+ * Equivalent to @c memset except that the prohibition on null pointer
+ * arguments is removed when @p n is 0.
+ */
+static inline void *sftp_memset(void *s, int ch, size_t n) {
+  if(n) {
+    assert(s);
+    return memset(s, ch, n);
+  }
+  return s;
+}
 
 /** @brief Whether to log to syslog
  *
- * Affects where fatal() writes to.
+ * Affects where sftp_fatal() writes to.
  */
-extern int log_syslog;
+extern int sftp_log_syslog;
 
 #endif /* UTILS_H */
 
diff --git a/v3.c b/v3.c
index b761f6b..0a028f1 100644
--- a/v3.c
+++ b/v3.c
@@ -50,12 +50,12 @@ int reverse_symlink;
 /* Encode/decode path names.  v3 does not know what encoding filenames use.  I
  * assume that the client and the server use the same encoding and so don't
  * perform any translation. */
-int sftp_v3_encode(struct sftpjob attribute((unused)) *job,
-                   char attribute((unused)) **path) {
+int sftp_v3_encode(struct sftpjob attribute((unused)) * job,
+                   char attribute((unused)) * *path) {
   return 0;
 }
 
-static uint32_t v3_decode(struct sftpjob attribute((unused)) *job, 
+static uint32_t v3_decode(struct sftpjob attribute((unused)) * job,
                           char **path) {
   /* Empty path means default directory */
   if(!**path)
@@ -65,8 +65,8 @@ static uint32_t v3_decode(struct sftpjob attribute((unused)) *job,
 
 /* Send a filename list as found in an SSH_FXP_NAME response.  The response
  * header and so on must be generated by the caller. */
-static void v3_sendnames(struct sftpjob *job, 
-                         int nnames, const struct sftpattr *names) {
+static void v3_sendnames(struct sftpjob *job, int nnames,
+                         const struct sftpattr *names) {
   time_t now;
   struct tm nowtime;
 
@@ -76,31 +76,30 @@ static void v3_sendnames(struct sftpjob *job,
   sftp_send_uint32(job->worker, nnames);
   while(nnames > 0) {
     sftp_send_path(job, job->worker, names->name);
-    sftp_send_string(job->worker, sftp_format_attr(job->a, names, nowtime.tm_year, 0));
+    sftp_send_string(job->worker,
+                     sftp_format_attr(job->a, names, nowtime.tm_year, 0));
     protocol->sendattrs(job, names);
     ++names;
     --nnames;
   }
 }
 
-static void v3_sendattrs(struct sftpjob *job,
-                         const struct sftpattr *attrs) {
+static void v3_sendattrs(struct sftpjob *job, const struct sftpattr *attrs) {
   uint32_t v3bits, m, a;
 
   /* The timestamp flags change between v3 and v4.  In the structure we always
    * use the v4+ bits, so we must translate. */
-  if((attrs->valid & (SSH_FILEXFER_ATTR_ACCESSTIME
-                      |SSH_FILEXFER_ATTR_MODIFYTIME))
-     == (SSH_FILEXFER_ATTR_ACCESSTIME
-         |SSH_FILEXFER_ATTR_MODIFYTIME))
-    v3bits = ((attrs->valid & (SSH_FILEXFER_ATTR_SIZE
-                               |SSH_FILEXFER_ATTR_UIDGID
-                               |SSH_FILEXFER_ATTR_PERMISSIONS))
-              |SSH_FILEXFER_ACMODTIME);
+  if((attrs->valid &
+      (SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME)) ==
+     (SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME))
+    v3bits =
+        ((attrs->valid & (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_UIDGID |
+                          SSH_FILEXFER_ATTR_PERMISSIONS)) |
+         SSH_FILEXFER_ACMODTIME);
   else
-    v3bits = (attrs->valid & (SSH_FILEXFER_ATTR_SIZE
-                              |SSH_FILEXFER_ATTR_UIDGID
-                              |SSH_FILEXFER_ATTR_PERMISSIONS));
+    v3bits =
+        (attrs->valid & (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_UIDGID |
+                         SSH_FILEXFER_ATTR_PERMISSIONS));
   sftp_send_uint32(job->worker, v3bits);
   if(v3bits & SSH_FILEXFER_ATTR_SIZE)
     sftp_send_uint64(job->worker, attrs->size);
@@ -119,11 +118,11 @@ static void v3_sendattrs(struct sftpjob *job,
      * bogus timestamps or have some other workaround, then delete the
      * checks. */
     if(m != attrs->mtime.seconds)
-      fatal("sending out-of-range mtime");
+      sftp_fatal("sending out-of-range mtime");
     if(a != attrs->atime.seconds)
-      fatal("sending out-of-range mtime");
-    sftp_send_uint32(job->worker, m);
+      sftp_fatal("sending out-of-range mtime");
     sftp_send_uint32(job->worker, a);
+    sftp_send_uint32(job->worker, m);
   }
   /* Note that we just discard unknown bits rather than reporting errors. */
 }
@@ -131,19 +130,19 @@ static void v3_sendattrs(struct sftpjob *job,
 static uint32_t v3_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
   uint32_t n, rc;
 
-  memset(attrs, 0, sizeof *attrs);
+  sftp_memset(attrs, 0, sizeof *attrs);
   if((rc = sftp_parse_uint32(job, &attrs->valid)) != SSH_FX_OK)
     return rc;
   if((attrs->valid & protocol->attrmask) != attrs->valid) {
-    D(("received attrs %#x but protocol %d only supports %#x",
-       attrs->valid, protocol->version, protocol->attrmask));
+    D(("received attrs %#x but protocol %d only supports %#x", attrs->valid,
+       protocol->version, protocol->attrmask));
     attrs->valid = 0;
     return SSH_FX_BAD_MESSAGE;
   }
   /* Translate v3 bits t v4+ bits */
   if(attrs->valid & SSH_FILEXFER_ACMODTIME)
-    attrs->valid |= (SSH_FILEXFER_ATTR_ACCESSTIME
-                     |SSH_FILEXFER_ATTR_MODIFYTIME);
+    attrs->valid |=
+        (SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME);
   /* Read the v3 fields */
   if(attrs->valid & SSH_FILEXFER_ATTR_SIZE)
     if((rc = sftp_parse_uint64(job, &attrs->size)) != SSH_FX_OK)
@@ -159,14 +158,30 @@ static uint32_t v3_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
       return rc;
     /* Fake up type field */
     switch(attrs->permissions & S_IFMT) {
-    case S_IFIFO: attrs->type = SSH_FILEXFER_TYPE_FIFO; break;
-    case S_IFCHR: attrs->type = SSH_FILEXFER_TYPE_CHAR_DEVICE; break;
-    case S_IFDIR: attrs->type = SSH_FILEXFER_TYPE_DIRECTORY; break;
-    case S_IFBLK: attrs->type = SSH_FILEXFER_TYPE_BLOCK_DEVICE; break;
-    case S_IFREG: attrs->type = SSH_FILEXFER_TYPE_REGULAR; break;
-    case S_IFLNK: attrs->type = SSH_FILEXFER_TYPE_SYMLINK; break;
-    case S_IFSOCK: attrs->type = SSH_FILEXFER_TYPE_SOCKET; break;
-    default: attrs->type = SSH_FILEXFER_TYPE_UNKNOWN; break;
+    case S_IFIFO:
+      attrs->type = SSH_FILEXFER_TYPE_FIFO;
+      break;
+    case S_IFCHR:
+      attrs->type = SSH_FILEXFER_TYPE_CHAR_DEVICE;
+      break;
+    case S_IFDIR:
+      attrs->type = SSH_FILEXFER_TYPE_DIRECTORY;
+      break;
+    case S_IFBLK:
+      attrs->type = SSH_FILEXFER_TYPE_BLOCK_DEVICE;
+      break;
+    case S_IFREG:
+      attrs->type = SSH_FILEXFER_TYPE_REGULAR;
+      break;
+    case S_IFLNK:
+      attrs->type = SSH_FILEXFER_TYPE_SYMLINK;
+      break;
+    case S_IFSOCK:
+      attrs->type = SSH_FILEXFER_TYPE_SOCKET;
+      break;
+    default:
+      attrs->type = SSH_FILEXFER_TYPE_UNKNOWN;
+      break;
     }
   } else
     attrs->type = SSH_FILEXFER_TYPE_UNKNOWN;
@@ -184,8 +199,8 @@ static uint32_t v3_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
     if((rc = sftp_parse_uint32(job, &n)) != SSH_FX_OK)
       return rc;
     while(n-- > 0) {
-      if((rc = sftp_parse_string(job, 0, 0)) != SSH_FX_OK
-         || (rc = sftp_parse_string(job, 0, 0)) != SSH_FX_OK)
+      if((rc = sftp_parse_string(job, 0, 0)) != SSH_FX_OK ||
+         (rc = sftp_parse_string(job, 0, 0)) != SSH_FX_OK)
         return rc;
     }
   }
@@ -194,7 +209,7 @@ static uint32_t v3_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
 
 /* Command implementations */
 
-uint32_t sftp_vany_already_init(struct sftpjob attribute((unused)) *job) {
+uint32_t sftp_vany_already_init(struct sftpjob attribute((unused)) * job) {
   /* Cannot initialize more than once */
   return SSH_FX_FAILURE;
 }
@@ -221,7 +236,7 @@ uint32_t sftp_vany_remove(struct sftpjob *job) {
 
 uint32_t sftp_vany_rmdir(struct sftpjob *job) {
   char *path;
-  
+
   if(readonly)
     return SSH_FX_PERMISSION_DENIED;
   pcheck(sftp_parse_path(job, &path));
@@ -275,11 +290,11 @@ uint32_t sftp_v34_rename(struct sftpjob *job) {
           return SSH_FX_FILE_ALREADY_EXISTS;
       }
 #endif
-      if(rename(oldpath, newpath) < 0) 
+      if(rename(oldpath, newpath) < 0)
         return HANDLER_ERRNO;
       else
         return SSH_FX_OK;
-    } else 
+    } else
       return HANDLER_ERRNO;
   } else if(unlink(oldpath) < 0) {
     const int save_errno = errno;
@@ -372,7 +387,7 @@ uint32_t sftp_vany_readlink(struct sftpjob *job) {
     }
     return HANDLER_ERRNO;
   }
-  memset(&attr, 0, sizeof attr);
+  sftp_memset(&attr, 0, sizeof attr);
   attr.name = result;
   sftp_send_begin(job->worker);
   sftp_send_uint8(job->worker, SSH_FXP_NAME);
@@ -392,7 +407,7 @@ uint32_t sftp_vany_opendir(struct sftpjob *job) {
   if(!(dp = opendir(path)))
     return HANDLER_ERRNO;
   sftp_handle_new_dir(&id, dp, path);
-  D(("...handle is %"PRIu32" %"PRIu32, id.id, id.tag));
+  D(("...handle is %" PRIu32 " %" PRIu32, id.id, id.tag));
   sftp_send_begin(job->worker);
   sftp_send_uint8(job->worker, SSH_FXP_HANDLE);
   sftp_send_uint32(job->worker, job->id);
@@ -411,14 +426,14 @@ uint32_t sftp_vany_readdir(struct sftpjob *job) {
   const char *path;
   char *childpath, *fullpath;
   struct stat sb;
-  
+
   pcheck(sftp_parse_handle(job, &id));
-  D(("sftp_vany_readdir %"PRIu32" %"PRIu32, id.id, id.tag));
+  D(("sftp_vany_readdir %" PRIu32 " %" PRIu32, id.id, id.tag));
   if((rc = sftp_handle_get_dir(&id, &dp, &path))) {
     sftp_send_status(job, rc, "invalid directory handle");
     return HANDLER_RESPONDED;
   }
-  memset(d, 0, sizeof d);
+  sftp_memset(d, 0, sizeof d);
   for(n = 0; n < MAXNAMES;) {
     /* readdir() has a slightly shonky interface - a null return can mean EOF
      * or error, and there is no guarantee that errno is reset to 0 on EOF. */
@@ -439,10 +454,10 @@ uint32_t sftp_vany_readdir(struct sftpjob *job) {
     sftp_stat_to_attrs(job->a, &sb, &d[n], 0xFFFFFFFF, childpath);
     d[n].name = childpath;
     ++n;
-    errno = 0;                          /* avoid error slippage from
-                                         * e.g. getpwuid() failure */
+    errno = 0; /* avoid error slippage from
+                * e.g. getpwuid() failure */
   }
-  
+
   if(errno)
     return HANDLER_ERRNO;
   if(n) {
@@ -458,9 +473,9 @@ uint32_t sftp_vany_readdir(struct sftpjob *job) {
 
 uint32_t sftp_vany_close(struct sftpjob *job) {
   struct handleid id;
-  
+
   pcheck(sftp_parse_handle(job, &id));
-  D(("sftp_vany_close %"PRIu32" %"PRIu32, id.id, id.tag));
+  D(("sftp_vany_close %" PRIu32 " %" PRIu32, id.id, id.tag));
   return sftp_handle_close(&id);
 }
 
@@ -470,7 +485,7 @@ uint32_t sftp_v345_realpath(struct sftpjob *job) {
 
   pcheck(sftp_parse_path(job, &path));
   D(("sftp_v345_realpath %s", path));
-  memset(&attr, 0, sizeof attr);
+  sftp_memset(&attr, 0, sizeof attr);
   attr.name = sftp_find_realpath(job->a, path, RP_READLINK);
   if(attr.name) {
     D(("...real path is %s", attr.name));
@@ -486,7 +501,7 @@ uint32_t sftp_v345_realpath(struct sftpjob *job) {
 
 /* Command code for the various _*STAT calls.  rc is the return value
  * from *stat() and SB is the buffer. */
-static uint32_t sftp_v3_stat_core(struct sftpjob *job, int rc, 
+static uint32_t sftp_v3_stat_core(struct sftpjob *job, int rc,
                                   const struct stat *sb) {
   struct sftpattr attrs;
 
@@ -494,7 +509,7 @@ static uint32_t sftp_v3_stat_core(struct sftpjob *job, int rc,
     /* We suppress owner/group name lookup since there is no way to communicate
      * it in protocol version 3 */
     sftp_stat_to_attrs(job->a, sb, &attrs,
-                  ~(uint32_t)SSH_FILEXFER_ATTR_OWNERGROUP, 0);
+                       ~(uint32_t)SSH_FILEXFER_ATTR_OWNERGROUP, 0);
     sftp_send_begin(job->worker);
     sftp_send_uint8(job->worker, SSH_FXP_ATTRS);
     sftp_send_uint32(job->worker, job->id);
@@ -530,7 +545,7 @@ static uint32_t sftp_v3_fstat(struct sftpjob *job) {
   uint32_t rc;
 
   pcheck(sftp_parse_handle(job, &id));
-  D(("sftp_v3_fstat %"PRIu32" %"PRIu32, id.id, id.tag));
+  D(("sftp_v3_fstat %" PRIu32 " %" PRIu32, id.id, id.tag));
   if((rc = sftp_handle_get_fd(&id, &fd, 0)))
     return rc;
   return sftp_v3_stat_core(job, fstat(fd, &sb), &sb);
@@ -562,11 +577,11 @@ uint32_t sftp_vany_fsetstat(struct sftpjob *job) {
     return SSH_FX_PERMISSION_DENIED;
   pcheck(sftp_parse_handle(job, &id));
   pcheck(protocol->parseattrs(job, &attrs));
-  D(("sftp_vany_fsetstat %"PRIu32" %"PRIu32, id.id, id.tag));
+  D(("sftp_vany_fsetstat %" PRIu32 " %" PRIu32, id.id, id.tag));
   /* Check owner/group */
   if((rc = sftp_normalize_ownergroup(job->a, &attrs)) != SSH_FX_OK)
     return rc;
-  if((rc = sftp_handle_get_fd(&id, &fd, 0))) 
+  if((rc = sftp_handle_get_fd(&id, &fd, 0)))
     return rc;
   return sftp_set_fstatus(job->a, fd, &attrs, 0);
 }
@@ -581,12 +596,12 @@ uint32_t sftp_vany_mkdir(struct sftpjob *job) {
   pcheck(sftp_parse_path(job, &path));
   pcheck(protocol->parseattrs(job, &attrs));
   D(("sftp_vany_mkdir %s", path));
-  attrs.valid &= ~SSH_FILEXFER_ATTR_SIZE; /* makes no sense */
+  attrs.valid &= (uint32_t)~SSH_FILEXFER_ATTR_SIZE; /* makes no sense */
   if(attrs.valid & SSH_FILEXFER_ATTR_PERMISSIONS) {
-    D(("initial permissions are %#o (%d decimal)",
-       attrs.permissions, attrs.permissions));
+    D(("initial permissions are %#o (%d decimal)", attrs.permissions,
+       attrs.permissions));
     /* If we're given initial permissions, use them  */
-    if(mkdir(path, attrs.permissions & 07777) < 0) 
+    if(mkdir(path, attrs.permissions & 07777) < 0)
       return HANDLER_ERRNO;
     /* Don't modify permissions later unless necessary */
     if(attrs.permissions == (attrs.permissions & 0777))
@@ -617,9 +632,9 @@ uint32_t sftp_v34_open(struct sftpjob *job) {
   pcheck(sftp_parse_path(job, &path));
   pcheck(sftp_parse_uint32(job, &pflags));
   pcheck(protocol->parseattrs(job, &attrs));
-  D(("sftp_v34_open %s %#"PRIx32, path, pflags));
+  D(("sftp_v34_open %s %#" PRIx32, path, pflags));
   /* Translate to v5/6 bits */
-  switch(pflags & (SSH_FXF_CREAT|SSH_FXF_TRUNC|SSH_FXF_EXCL)) {
+  switch(pflags & (SSH_FXF_CREAT | SSH_FXF_TRUNC | SSH_FXF_EXCL)) {
   case 0:
     flags = SSH_FXF_OPEN_EXISTING;
     break;
@@ -632,11 +647,11 @@ uint32_t sftp_v34_open(struct sftpjob *job) {
   case SSH_FXF_CREAT:
     flags = SSH_FXF_OPEN_OR_CREATE;
     break;
-  case SSH_FXF_CREAT|SSH_FXF_TRUNC:
+  case SSH_FXF_CREAT | SSH_FXF_TRUNC:
     flags = SSH_FXF_CREATE_TRUNCATE;
     break;
-  case SSH_FXF_CREAT|SSH_FXF_EXCL:
-  case SSH_FXF_CREAT|SSH_FXF_TRUNC|SSH_FXF_EXCL: /* nonsensical */
+  case SSH_FXF_CREAT | SSH_FXF_EXCL:
+  case SSH_FXF_CREAT | SSH_FXF_TRUNC | SSH_FXF_EXCL: /* nonsensical */
     flags = SSH_FXF_CREATE_NEW;
     break;
   default:
@@ -645,9 +660,9 @@ uint32_t sftp_v34_open(struct sftpjob *job) {
   if(pflags & SSH_FXF_TEXT)
     flags |= SSH_FXF_TEXT_MODE;
   if(pflags & SSH_FXF_READ)
-    desired_access |= ACE4_READ_DATA|ACE4_READ_ATTRIBUTES;
+    desired_access |= ACE4_READ_DATA | ACE4_READ_ATTRIBUTES;
   if(pflags & SSH_FXF_WRITE)
-    desired_access |= ACE4_WRITE_DATA|ACE4_WRITE_ATTRIBUTES;
+    desired_access |= ACE4_WRITE_DATA | ACE4_WRITE_ATTRIBUTES;
   if(pflags & SSH_FXF_APPEND) {
     flags |= SSH_FXF_APPEND_DATA;
     desired_access |= ACE4_APPEND_DATA;
@@ -666,7 +681,8 @@ uint32_t sftp_vany_read(struct sftpjob *job) {
   pcheck(sftp_parse_handle(job, &id));
   pcheck(sftp_parse_uint64(job, &offset));
   pcheck(sftp_parse_uint32(job, &len));
-  D(("sftp_vany_read %"PRIx32" %"PRIu32" %"PRIu32": %"PRIu32" bytes at %"PRIu64,
+  D(("sftp_vany_read %" PRIx32 " %" PRIu32 " %" PRIu32 ": %" PRIu32
+     " bytes at %" PRIu64,
      job->id, id.id, id.tag, len, offset));
   if(len > MAXREAD)
     len = MAXREAD;
@@ -677,7 +693,7 @@ uint32_t sftp_vany_read(struct sftpjob *job) {
   sftp_send_uint8(job->worker, SSH_FXP_DATA);
   sftp_send_uint32(job->worker, job->id);
   sftp_send_need(job->worker, len + 4);
-  if(flags & (HANDLE_TEXT|HANDLE_APPEND))
+  if(flags & (HANDLE_TEXT | HANDLE_APPEND))
     n = read(fd, job->worker->buffer + job->worker->bufused + 4, len);
   else
     n = pread(fd, job->worker->buffer + job->worker->bufused + 4, len, offset);
@@ -712,13 +728,13 @@ uint32_t sftp_vany_write(struct sftpjob *job) {
   pcheck(sftp_parse_uint32(job, &len));
   if(len > job->left)
     return SSH_FX_BAD_MESSAGE;
-  D(("sftp_vany_write %"PRIu32" %"PRIu32": %"PRIu32" bytes at %"PRIu64,
+  D(("sftp_vany_write %" PRIu32 " %" PRIu32 ": %" PRIu32 " bytes at %" PRIu64,
      id.id, id.tag, len, offset));
   if((rc = sftp_handle_get_fd(&id, &fd, &flags)))
     return rc;
   while(len > 0) {
     /* Short writes aren't allowed so we loop around writing more */
-    if(flags & (HANDLE_TEXT|HANDLE_APPEND))
+    if(flags & (HANDLE_TEXT | HANDLE_APPEND))
       n = write(fd, job->ptr, len);
     else
       n = pwrite(fd, job->ptr, len, offset);
@@ -740,7 +756,7 @@ uint32_t sftp_vany_posix_rename(struct sftpjob *job) {
   pcheck(sftp_parse_path(job, &oldpath));
   pcheck(sftp_parse_path(job, &newpath));
   D(("sftp_vany_posix_rename %s %s", oldpath, newpath));
-  if(rename(oldpath, newpath) < 0) 
+  if(rename(oldpath, newpath) < 0)
     return HANDLER_ERRNO;
   else
     return SSH_FX_OK;
@@ -770,8 +786,9 @@ uint32_t sftp_vany_statfs(struct sftpjob *job) {
   return HANDLER_RESPONDED;
 }
 
-static uint32_t sftp_vany_statvfs_send(struct sftpjob *job, int rc, struct statvfs *fs) {
-  if (rc < 0)
+static uint32_t sftp_vany_statvfs_send(struct sftpjob *job, int rc,
+                                       struct statvfs *fs) {
+  if(rc < 0)
     return HANDLER_ERRNO;
   sftp_send_begin(job->worker);
   sftp_send_uint8(job->worker, SSH_FXP_EXTENDED_REPLY);
@@ -785,7 +802,8 @@ static uint32_t sftp_vany_statvfs_send(struct sftpjob *job, int rc, struct statv
   sftp_send_uint64(job->worker, fs->f_ffree);
   sftp_send_uint64(job->worker, fs->f_favail);
   sftp_send_uint64(job->worker, fs->f_fsid);
-  sftp_send_uint64(job->worker, (fs->f_flag & ST_RDONLY ? 1 : 0) | (fs->f_flag & ST_NOSUID ? 2 : 0));
+  sftp_send_uint64(job->worker, (fs->f_flag & ST_RDONLY ? 1 : 0) |
+                                    (fs->f_flag & ST_NOSUID ? 2 : 0));
   sftp_send_uint64(job->worker, fs->f_namemax);
   sftp_send_end(job->worker);
   return HANDLER_RESPONDED;
@@ -807,7 +825,7 @@ uint32_t sftp_vany_fstatvfs(struct sftpjob *job) {
   uint32_t rc;
 
   pcheck(sftp_parse_handle(job, &id));
-  D(("sftp_vany_fstatvfs %"PRIu32" %"PRIu32, id.id, id.tag));
+  D(("sftp_vany_fstatvfs %" PRIu32 " %" PRIu32, id.id, id.tag));
   if((rc = sftp_handle_get_fd(&id, &fd, 0)))
     return rc;
   return sftp_vany_statvfs_send(job, fstatvfs(fd, &fs), &fs);
@@ -819,10 +837,10 @@ uint32_t sftp_vany_fsync(struct sftpjob *job) {
   uint32_t rc;
 
   pcheck(sftp_parse_handle(job, &id));
-  D(("sftp_v3_fstat %"PRIu32" %"PRIu32, id.id, id.tag));
+  D(("sftp_v3_fstat %" PRIu32 " %" PRIu32, id.id, id.tag));
   if((rc = sftp_handle_get_fd(&id, &fd, 0)))
     return rc;
-  if (fsync(fd) < 0)
+  if(fsync(fd) < 0)
     return HANDLER_ERRNO;
   return SSH_FX_OK;
 }
@@ -833,7 +851,7 @@ uint32_t sftp_vany_hardlink(struct sftpjob *job) {
   /* See also comment in v3.c for SSH_FXP_SYMLINK */
   if(readonly)
     return SSH_FX_PERMISSION_DENIED;
-  pcheck(sftp_parse_path(job, &oldpath));    /* aka existing-path/target-paths */
+  pcheck(sftp_parse_path(job, &oldpath)); /* aka existing-path/target-paths */
   pcheck(sftp_parse_path(job, &newlinkpath));
   D(("sftp_hardlink %s %s", oldpath, newlinkpath));
   if(link(oldpath, newlinkpath) < 0)
@@ -842,56 +860,53 @@ uint32_t sftp_vany_hardlink(struct sftpjob *job) {
 }
 
 static const struct sftpcmd sftpv3tab[] = {
-  { SSH_FXP_INIT, sftp_vany_already_init },
-  { SSH_FXP_OPEN, sftp_v34_open },
-  { SSH_FXP_CLOSE, sftp_vany_close },
-  { SSH_FXP_READ, sftp_vany_read },
-  { SSH_FXP_WRITE, sftp_vany_write },
-  { SSH_FXP_LSTAT, sftp_v3_lstat },
-  { SSH_FXP_FSTAT, sftp_v3_fstat },
-  { SSH_FXP_SETSTAT, sftp_vany_setstat },
-  { SSH_FXP_FSETSTAT, sftp_vany_fsetstat },
-  { SSH_FXP_OPENDIR, sftp_vany_opendir },
-  { SSH_FXP_READDIR, sftp_vany_readdir },
-  { SSH_FXP_REMOVE, sftp_vany_remove },
-  { SSH_FXP_MKDIR, sftp_vany_mkdir },
-  { SSH_FXP_RMDIR, sftp_vany_rmdir },
-  { SSH_FXP_REALPATH, sftp_v345_realpath },
-  { SSH_FXP_STAT, sftp_v3_stat },
-  { SSH_FXP_RENAME, sftp_v34_rename },
-  { SSH_FXP_READLINK, sftp_vany_readlink },
-  { SSH_FXP_SYMLINK, sftp_v345_symlink },
-  { SSH_FXP_EXTENDED, sftp_vany_extended }
-};
+    {SSH_FXP_INIT, sftp_vany_already_init},
+    {SSH_FXP_OPEN, sftp_v34_open},
+    {SSH_FXP_CLOSE, sftp_vany_close},
+    {SSH_FXP_READ, sftp_vany_read},
+    {SSH_FXP_WRITE, sftp_vany_write},
+    {SSH_FXP_LSTAT, sftp_v3_lstat},
+    {SSH_FXP_FSTAT, sftp_v3_fstat},
+    {SSH_FXP_SETSTAT, sftp_vany_setstat},
+    {SSH_FXP_FSETSTAT, sftp_vany_fsetstat},
+    {SSH_FXP_OPENDIR, sftp_vany_opendir},
+    {SSH_FXP_READDIR, sftp_vany_readdir},
+    {SSH_FXP_REMOVE, sftp_vany_remove},
+    {SSH_FXP_MKDIR, sftp_vany_mkdir},
+    {SSH_FXP_RMDIR, sftp_vany_rmdir},
+    {SSH_FXP_REALPATH, sftp_v345_realpath},
+    {SSH_FXP_STAT, sftp_v3_stat},
+    {SSH_FXP_RENAME, sftp_v34_rename},
+    {SSH_FXP_READLINK, sftp_vany_readlink},
+    {SSH_FXP_SYMLINK, sftp_v345_symlink},
+    {SSH_FXP_EXTENDED, sftp_vany_extended}};
 
 static const struct sftpextension v3_extensions[] = {
-  { "fsync@openssh.com", "1", sftp_vany_fsync },
-  { "hardlink@openssh.com", "1", sftp_vany_hardlink },
-  { "posix-rename@openssh.com", "1", sftp_vany_posix_rename },
-  { "posix-rename@openssh.org", "", sftp_vany_posix_rename },
-  { "space-available", "", sftp_vany_space_available },
-  { "statfs@openssh.org", "", sftp_vany_statfs },
-  { "statvfs@openssh.com", "2", sftp_vany_statvfs },
-  { "fstatvfs@openssh.com", "2", sftp_vany_fstatvfs },
+    {"fsync@openssh.com", "1", sftp_vany_fsync},
+    {"hardlink@openssh.com", "1", sftp_vany_hardlink},
+    {"posix-rename@openssh.com", "1", sftp_vany_posix_rename},
+    {"posix-rename@openssh.org", "", sftp_vany_posix_rename},
+    {"space-available", "", sftp_vany_space_available},
+    {"statfs@openssh.org", "", sftp_vany_statfs},
+    {"statvfs@openssh.com", "2", sftp_vany_statvfs},
+    {"fstatvfs@openssh.com", "2", sftp_vany_fstatvfs},
 };
 
 const struct sftpprotocol sftp_v3 = {
-  sizeof sftpv3tab / sizeof (struct sftpcmd), /* ncommands */
-  sftpv3tab,                                  /* commands */
-  3,                                          /* version */
-  (SSH_FILEXFER_ATTR_SIZE
-   |SSH_FILEXFER_ATTR_PERMISSIONS
-   |SSH_FILEXFER_ATTR_ACCESSTIME
-   |SSH_FILEXFER_ATTR_MODIFYTIME
-   |SSH_FILEXFER_ATTR_UIDGID),                /* attrmask */
-  SSH_FX_OP_UNSUPPORTED,                      /* maxstatus */
-  v3_sendnames,
-  v3_sendattrs,
-  v3_parseattrs,
-  sftp_v3_encode,
-  v3_decode,
-  sizeof v3_extensions / sizeof (struct sftpextension),
-  v3_extensions,                        /* extensions */
+    sizeof sftpv3tab / sizeof(struct sftpcmd), /* ncommands */
+    sftpv3tab,                                 /* commands */
+    3,                                         /* version */
+    (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+     SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+     SSH_FILEXFER_ATTR_UIDGID), /* attrmask */
+    SSH_FX_OP_UNSUPPORTED,      /* maxstatus */
+    v3_sendnames,
+    v3_sendattrs,
+    v3_parseattrs,
+    sftp_v3_encode,
+    v3_decode,
+    sizeof v3_extensions / sizeof(struct sftpextension),
+    v3_extensions, /* extensions */
 };
 
 /*
diff --git a/v4.c b/v4.c
index 4a2084b..5441571 100644
--- a/v4.c
+++ b/v4.c
@@ -29,16 +29,15 @@
 #include "stat.h"
 #include "handle.h"
 #include "serialize.h"
+#include "utils.h"
 #include <string.h>
 
-int sftp_v456_encode(struct sftpjob *job,
-		char **path) {
+int sftp_v456_encode(struct sftpjob *job, char **path) {
   /* Translate local to UTF-8 */
   return sftp_iconv(job->a, job->worker->local_to_utf8, path);
 }
 
-uint32_t sftp_v456_decode(struct sftpjob *job, 
-                     char **path) {
+uint32_t sftp_v456_decode(struct sftpjob *job, char **path) {
   /* Empty path means default directory */
   if(!**path)
     *path = (char *)".";
@@ -49,8 +48,7 @@ uint32_t sftp_v456_decode(struct sftpjob *job,
     return SSH_FX_OK;
 }
 
-void sftp_v456_sendattrs(struct sftpjob *job,
- 		    const struct sftpattr *attrs) {
+void sftp_v456_sendattrs(struct sftpjob *job, const struct sftpattr *attrs) {
   const uint32_t valid = attrs->valid & protocol->attrmask;
 
   sftp_send_uint32(job->worker, valid);
@@ -110,12 +108,12 @@ void sftp_v456_sendattrs(struct sftpjob *job,
 uint32_t sftp_v456_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
   uint32_t n, rc;
 
-  memset(attrs, 0, sizeof *attrs);
+  sftp_memset(attrs, 0, sizeof *attrs);
   if((rc = sftp_parse_uint32(job, &attrs->valid)) != SSH_FX_OK)
     return rc;
   if((attrs->valid & protocol->attrmask) != attrs->valid) {
-    D(("received attrs %#x but protocol %d only supports %#x",
-       attrs->valid, protocol->version, protocol->attrmask));
+    D(("received attrs %#x but protocol %d only supports %#x", attrs->valid,
+       protocol->version, protocol->attrmask));
     attrs->valid = 0;
     return SSH_FX_BAD_MESSAGE;
   }
@@ -135,28 +133,33 @@ uint32_t sftp_v456_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
       return rc;
   }
   if(attrs->valid & SSH_FILEXFER_ATTR_ACCESSTIME) {
-    if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->atime.seconds)) != SSH_FX_OK)
+    if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->atime.seconds)) !=
+       SSH_FX_OK)
       return rc;
     if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
       if((rc = sftp_parse_uint32(job, &attrs->atime.nanoseconds)) != SSH_FX_OK)
         return rc;
   }
   if(attrs->valid & SSH_FILEXFER_ATTR_CREATETIME) {
-    if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->createtime.seconds)) != SSH_FX_OK)
+    if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->createtime.seconds)) !=
+       SSH_FX_OK)
       return rc;
     if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
-      if((rc = sftp_parse_uint32(job, &attrs->createtime.nanoseconds)) != SSH_FX_OK)
+      if((rc = sftp_parse_uint32(job, &attrs->createtime.nanoseconds)) !=
+         SSH_FX_OK)
         return rc;
   }
   if(attrs->valid & SSH_FILEXFER_ATTR_MODIFYTIME) {
-    if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->mtime.seconds)) != SSH_FX_OK)
+    if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->mtime.seconds)) !=
+       SSH_FX_OK)
       return rc;
     if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
       if((rc = sftp_parse_uint32(job, &attrs->mtime.nanoseconds)) != SSH_FX_OK)
         return rc;
   }
   if(attrs->valid & SSH_FILEXFER_ATTR_CTIME) {
-    if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->ctime.seconds)) != SSH_FX_OK)
+    if((rc = sftp_parse_uint64(job, (uint64_t *)&attrs->ctime.seconds)) !=
+       SSH_FX_OK)
       return rc;
     if(attrs->valid & SSH_FILEXFER_ATTR_SUBSECOND_TIMES)
       if((rc = sftp_parse_uint32(job, &attrs->ctime.nanoseconds)) != SSH_FX_OK)
@@ -206,8 +209,8 @@ uint32_t sftp_v456_parseattrs(struct sftpjob *job, struct sftpattr *attrs) {
 
 /* Send a filename list as found in an SSH_FXP_NAME response.  The response
  * header and so on must be generated by the caller. */
-void sftp_v456_sendnames(struct sftpjob *job, 
-		    int nnames, const struct sftpattr *names) {
+void sftp_v456_sendnames(struct sftpjob *job, int nnames,
+                         const struct sftpattr *names) {
   /* We'd like to know what year we're in for dates in longname */
   sftp_send_uint32(job->worker, nnames);
   while(nnames > 0) {
@@ -220,7 +223,7 @@ void sftp_v456_sendnames(struct sftpjob *job,
 
 /* Command code for the various _*STAT calls.  rc is the return value
  * from *stat() and SB is the buffer. */
-static uint32_t sftp_v456_stat_core(struct sftpjob *job, int rc, 
+static uint32_t sftp_v456_stat_core(struct sftpjob *job, int rc,
                                     const struct stat *sb, const char *path) {
   struct sftpattr attrs;
   uint32_t flags;
@@ -263,65 +266,61 @@ uint32_t sftp_v456_fstat(struct sftpjob *job) {
   uint32_t rc;
 
   pcheck(sftp_parse_handle(job, &id));
-  D(("sftp_fstat %"PRIu32" %"PRIu32, id.id, id.tag));
+  D(("sftp_fstat %" PRIu32 " %" PRIu32, id.id, id.tag));
   if((rc = sftp_handle_get_fd(&id, &fd, 0)))
     return rc;
   return sftp_v456_stat_core(job, fstat(fd, &sb), &sb, 0);
 }
 
 static const struct sftpcmd sftpv4tab[] = {
-  { SSH_FXP_INIT, sftp_vany_already_init },
-  { SSH_FXP_OPEN, sftp_v34_open },
-  { SSH_FXP_CLOSE, sftp_vany_close },
-  { SSH_FXP_READ, sftp_vany_read },
-  { SSH_FXP_WRITE, sftp_vany_write },
-  { SSH_FXP_LSTAT, sftp_v456_lstat },
-  { SSH_FXP_FSTAT, sftp_v456_fstat },
-  { SSH_FXP_SETSTAT, sftp_vany_setstat },
-  { SSH_FXP_FSETSTAT, sftp_vany_fsetstat },
-  { SSH_FXP_OPENDIR, sftp_vany_opendir },
-  { SSH_FXP_READDIR, sftp_vany_readdir },
-  { SSH_FXP_REMOVE, sftp_vany_remove },
-  { SSH_FXP_MKDIR, sftp_vany_mkdir },
-  { SSH_FXP_RMDIR, sftp_vany_rmdir },
-  { SSH_FXP_REALPATH, sftp_v345_realpath },
-  { SSH_FXP_STAT, sftp_v456_stat },
-  { SSH_FXP_RENAME, sftp_v34_rename },
-  { SSH_FXP_READLINK, sftp_vany_readlink },
-  { SSH_FXP_SYMLINK, sftp_v345_symlink },
-  { SSH_FXP_EXTENDED, sftp_vany_extended }
-};
+    {SSH_FXP_INIT, sftp_vany_already_init},
+    {SSH_FXP_OPEN, sftp_v34_open},
+    {SSH_FXP_CLOSE, sftp_vany_close},
+    {SSH_FXP_READ, sftp_vany_read},
+    {SSH_FXP_WRITE, sftp_vany_write},
+    {SSH_FXP_LSTAT, sftp_v456_lstat},
+    {SSH_FXP_FSTAT, sftp_v456_fstat},
+    {SSH_FXP_SETSTAT, sftp_vany_setstat},
+    {SSH_FXP_FSETSTAT, sftp_vany_fsetstat},
+    {SSH_FXP_OPENDIR, sftp_vany_opendir},
+    {SSH_FXP_READDIR, sftp_vany_readdir},
+    {SSH_FXP_REMOVE, sftp_vany_remove},
+    {SSH_FXP_MKDIR, sftp_vany_mkdir},
+    {SSH_FXP_RMDIR, sftp_vany_rmdir},
+    {SSH_FXP_REALPATH, sftp_v345_realpath},
+    {SSH_FXP_STAT, sftp_v456_stat},
+    {SSH_FXP_RENAME, sftp_v34_rename},
+    {SSH_FXP_READLINK, sftp_vany_readlink},
+    {SSH_FXP_SYMLINK, sftp_v345_symlink},
+    {SSH_FXP_EXTENDED, sftp_vany_extended}};
 
 static const struct sftpextension v4_extensions[] = {
-  { "fsync@openssh.com", "1", sftp_vany_fsync },
-  { "hardlink@openssh.com", "1", sftp_vany_hardlink },
-  { "posix-rename@openssh.com", "1", sftp_vany_posix_rename },
-  { "posix-rename@openssh.org", "", sftp_vany_posix_rename },
-  { "space-available", "", sftp_vany_space_available },
-  { "statfs@openssh.org", "", sftp_vany_statfs },
-  { "text-seek", "", sftp_vany_text_seek },
-  { "statvfs@openssh.com", "2", sftp_vany_statvfs },
-  { "fstatvfs@openssh.com", "2", sftp_vany_fstatvfs },
+    {"fsync@openssh.com", "1", sftp_vany_fsync},
+    {"hardlink@openssh.com", "1", sftp_vany_hardlink},
+    {"posix-rename@openssh.com", "1", sftp_vany_posix_rename},
+    {"posix-rename@openssh.org", "", sftp_vany_posix_rename},
+    {"space-available", "", sftp_vany_space_available},
+    {"statfs@openssh.org", "", sftp_vany_statfs},
+    {"text-seek", "", sftp_vany_text_seek},
+    {"statvfs@openssh.com", "2", sftp_vany_statvfs},
+    {"fstatvfs@openssh.com", "2", sftp_vany_fstatvfs},
 };
 
 const struct sftpprotocol sftp_v4 = {
-  sizeof sftpv4tab / sizeof (struct sftpcmd),
-  sftpv4tab,
-  4,
-  (SSH_FILEXFER_ATTR_SIZE
-   |SSH_FILEXFER_ATTR_PERMISSIONS
-   |SSH_FILEXFER_ATTR_ACCESSTIME
-   |SSH_FILEXFER_ATTR_MODIFYTIME
-   |SSH_FILEXFER_ATTR_OWNERGROUP
-   |SSH_FILEXFER_ATTR_SUBSECOND_TIMES),
-  SSH_FX_NO_MEDIA,
-  sftp_v456_sendnames,
-  sftp_v456_sendattrs,
-  sftp_v456_parseattrs,
-  sftp_v456_encode,
-  sftp_v456_decode,
-  sizeof v4_extensions / sizeof (struct sftpextension),
-  v4_extensions,                        /* extensions */
+    sizeof sftpv4tab / sizeof(struct sftpcmd),
+    sftpv4tab,
+    4,
+    (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+     SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+     SSH_FILEXFER_ATTR_OWNERGROUP | SSH_FILEXFER_ATTR_SUBSECOND_TIMES),
+    SSH_FX_NO_MEDIA,
+    sftp_v456_sendnames,
+    sftp_v456_sendattrs,
+    sftp_v456_parseattrs,
+    sftp_v456_encode,
+    sftp_v456_decode,
+    sizeof v4_extensions / sizeof(struct sftpextension),
+    v4_extensions, /* extensions */
 };
 
 /*
diff --git a/v5.c b/v5.c
index 23d690f..8790ca1 100644
--- a/v5.c
+++ b/v5.c
@@ -45,13 +45,13 @@ uint32_t sftp_v56_open(struct sftpjob *job) {
   pcheck(sftp_parse_uint32(job, &desired_access));
   pcheck(sftp_parse_uint32(job, &flags));
   pcheck(protocol->parseattrs(job, &attrs));
-  D(("sftp_v56_open %s %#"PRIx32" %#"PRIx32, path, desired_access, flags));
+  D(("sftp_v56_open %s %#" PRIx32 " %#" PRIx32, path, desired_access, flags));
   return sftp_generic_open(job, path, desired_access, flags, &attrs);
 }
 
 uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
-                      uint32_t desired_access, uint32_t flags,
-                      struct sftpattr *attrs) {
+                           uint32_t desired_access, uint32_t flags,
+                           struct sftpattr *attrs) {
   mode_t initial_permissions;
   int created, open_flags, fd;
   struct stat sb;
@@ -59,7 +59,8 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
   unsigned sftp_handle_flags = 0;
   uint32_t rc;
 
-  D(("sftp_generic_open %s %#"PRIx32" %#"PRIx32, path, desired_access, flags));
+  D(("sftp_generic_open %s %#" PRIx32 " %#" PRIx32, path, desired_access,
+     flags));
   /* Check owner/group */
   if((rc = sftp_normalize_ownergroup(job->a, attrs)) != SSH_FX_OK)
     return rc;
@@ -75,15 +76,13 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
    * the specification taken literally prohibits UNIX implementations, I assume
    * that it is in error.
    */
-  switch(desired_access & (ACE4_READ_DATA|ACE4_WRITE_DATA)) {
-  case 0:                               /* probably a broken client */
+  switch(desired_access & (ACE4_READ_DATA | ACE4_WRITE_DATA)) {
+  case 0: /* probably a broken client */
   case ACE4_READ_DATA:
     D(("O_RDONLY"));
     open_flags = O_RDONLY;
-    if(desired_access & (ACE4_WRITE_NAMED_ATTRS
-                         |ACE4_WRITE_ATTRIBUTES
-                         |ACE4_WRITE_ACL
-                         |ACE4_WRITE_OWNER))
+    if(desired_access & (ACE4_WRITE_NAMED_ATTRS | ACE4_WRITE_ATTRIBUTES |
+                         ACE4_WRITE_ACL | ACE4_WRITE_OWNER))
       return SSH_FX_PERMISSION_DENIED;
     break;
   case ACE4_WRITE_DATA:
@@ -91,38 +90,37 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
       return SSH_FX_PERMISSION_DENIED;
     D(("O_WRONLY"));
     open_flags = O_WRONLY;
-    if(desired_access & (ACE4_READ_NAMED_ATTRS
-                         |ACE4_READ_ATTRIBUTES
-                         |ACE4_READ_ACL))
+    if(desired_access &
+       (ACE4_READ_NAMED_ATTRS | ACE4_READ_ATTRIBUTES | ACE4_READ_ACL))
       return SSH_FX_PERMISSION_DENIED;
     break;
-  case ACE4_READ_DATA|ACE4_WRITE_DATA:
+  case ACE4_READ_DATA | ACE4_WRITE_DATA:
     if(readonly)
       return SSH_FX_PERMISSION_DENIED;
     D(("O_RDWR"));
     open_flags = O_RDWR;
     break;
   default:
-    fatal("bitwise operators have broken");
+    sftp_fatal("bitwise operators have broken");
   }
   /* UNIX systems generally do not allow the owner to be changed by
    * non-superusers. */
   if((desired_access & ACE4_WRITE_OWNER) && getuid())
     return SSH_FX_PERMISSION_DENIED;
-  /* LIST_DIRECTORY, ADD_FILE, ADD_SUBDIRECTORY and DELETE_CHILD don't make
-   * sense for regular files.  We ignore them, regarding a grant of permission
-   * as not implying that the operation can possibly work.
-   *
-   * Similary SYNCHRONIZE and EXECUTE we're happy to grant permission for even
-   * if there's no way to take advantage of that permission.
-   *
-   * DELETE is always possible and nothing to do with opening the file.
-   */
+    /* LIST_DIRECTORY, ADD_FILE, ADD_SUBDIRECTORY and DELETE_CHILD don't make
+     * sense for regular files.  We ignore them, regarding a grant of permission
+     * as not implying that the operation can possibly work.
+     *
+     * Similary SYNCHRONIZE and EXECUTE we're happy to grant permission for even
+     * if there's no way to take advantage of that permission.
+     *
+     * DELETE is always possible and nothing to do with opening the file.
+     */
 #ifdef O_NOCTTY
   /* We don't want to accidentally acquire a controlling terminal. */
   open_flags |= O_NOCTTY;
 #endif
-  if(flags & (SSH_FXF_APPEND_DATA|SSH_FXF_APPEND_DATA_ATOMIC)) {
+  if(flags & (SSH_FXF_APPEND_DATA | SSH_FXF_APPEND_DATA_ATOMIC)) {
     /* We always use O_APPEND for appending so we always give atomic append. */
     D(("O_APPEND"));
     open_flags |= O_APPEND;
@@ -130,7 +128,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
   }
   if(flags & SSH_FXF_TEXT_MODE)
     sftp_handle_flags |= HANDLE_TEXT;
-  if(flags & (SSH_FXF_BLOCK_READ|SSH_FXF_BLOCK_WRITE|SSH_FXF_BLOCK_DELETE))
+  if(flags & (SSH_FXF_BLOCK_READ | SSH_FXF_BLOCK_WRITE | SSH_FXF_BLOCK_DELETE))
     return SSH_FX_OP_UNSUPPORTED;
   if(flags & SSH_FXF_NOFOLLOW) {
 #ifdef O_NOFOLLOW
@@ -154,9 +152,9 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
   } else
     /* Otherwise be conservative */
     initial_permissions = DEFAULT_PERMISSIONS & 0666;
-  if(readonly
-     && ((flags & SSH_FXF_ACCESS_DISPOSITION) != SSH_FXF_OPEN_EXISTING
-         || (flags & SSH_FXF_DELETE_ON_CLOSE))) {
+  if(readonly &&
+     ((flags & SSH_FXF_ACCESS_DISPOSITION) != SSH_FXF_OPEN_EXISTING ||
+      (flags & SSH_FXF_DELETE_ON_CLOSE))) {
     return SSH_FX_PERMISSION_DENIED;
   }
   switch(flags & SSH_FXF_ACCESS_DISPOSITION) {
@@ -165,16 +163,16 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
     if(flags & SSH_FXF_NOFOLLOW) {
       /* O_EXCL is just right if we don't want to follow links. */
       D(("SSH_FXF_CREATE_NEW|SSH_FXF_NOFOLLOW -> O_CREAT|O_EXCL"));
-      fd = open(path, open_flags|O_CREAT|O_EXCL, initial_permissions);
+      fd = open(path, open_flags | O_CREAT | O_EXCL, initial_permissions);
       created = 1;
     } else {
       /* O_EXCL will refuse to follow links so that's no good here.  We do a
-       * racy test and open since that's the best available. */ 
+       * racy test and open since that's the best available. */
       D(("SSH_FXF_CREATE_NEW -> test for existence"));
-      if(stat(path, &sb) == 0) 
+      if(stat(path, &sb) == 0)
         return SSH_FX_FILE_ALREADY_EXISTS;
       D(("SSH_FXF_CREATE_NEW -> O_CREAT"));
-      fd = open(path, open_flags|O_CREAT, initial_permissions);
+      fd = open(path, open_flags | O_CREAT, initial_permissions);
       created = 1;
     }
     break;
@@ -188,7 +186,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
       D(("SSH_FXF_OPEN_OR_TRUNCATE -> not O_TRUNC"));
     if(flags & SSH_FXF_NOFOLLOW) {
       D(("SSH_FXF_*|SSH_FXF_NOFOLLOW -> O_CREAT|O_EXCL"));
-      fd = open(path, open_flags|O_CREAT|O_EXCL, initial_permissions);
+      fd = open(path, open_flags | O_CREAT | O_EXCL, initial_permissions);
       if(fd >= 0)
         /* The file did not exist before */
         created = 1;
@@ -204,7 +202,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
         fd = open(path, open_flags, initial_permissions);
         created = 0;
       } else
-        created = 0;                    /* quieten compiler */
+        created = 0; /* quieten compiler */
     } else {
       /* As above we cannot use O_EXCL in this case as it'll refuse to follow
        * symlinks. */
@@ -220,7 +218,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
          * you get that file (perhaps truncated)!  We can't use O_EXCL here
          * because as observed so there is really no way round this. */
         D(("SSH_FXF_* -> O_CREAT"));
-        fd = open(path, open_flags|O_CREAT, initial_permissions);
+        fd = open(path, open_flags | O_CREAT, initial_permissions);
         created = 0;
       }
     }
@@ -250,7 +248,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
     }
 #endif
     D(("SSH_FXF_TRUNCATE_EXISTING -> O_TRUNC"));
-    fd = open(path, open_flags|O_TRUNC, initial_permissions);
+    fd = open(path, open_flags | O_TRUNC, initial_permissions);
     created = 0;
     break;
   default:
@@ -262,9 +260,9 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
     return SSH_FX_FILE_IS_A_DIRECTORY;
   }
   if(fd < 0) {
-    if(((flags & SSH_FXF_ACCESS_DISPOSITION) == SSH_FXF_OPEN_EXISTING
-        || (flags & SSH_FXF_ACCESS_DISPOSITION) == SSH_FXF_TRUNCATE_EXISTING)
-       && errno == ENOENT) {
+    if(((flags & SSH_FXF_ACCESS_DISPOSITION) == SSH_FXF_OPEN_EXISTING ||
+        (flags & SSH_FXF_ACCESS_DISPOSITION) == SSH_FXF_TRUNCATE_EXISTING) &&
+       errno == ENOENT) {
       /* The client could do the extra check but at the cost of a round trip,
        * so it makes some sense to do it and return the alternative status.
        * This is of rather limited use as the client has no way to know that we
@@ -272,14 +270,13 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
        * alternative error message might clue in users occasionally. */
       if(lstat(sftp_dirname(job->a, path), &sb) < 0)
         return SSH_FX_NO_SUCH_PATH;
-      errno = ENOENT;                   /* restore errno just in case */
+      errno = ENOENT; /* restore errno just in case */
     }
 #ifdef O_NOFOLLOW
     /* If we couldn't open the file because we declined to follow a symlink
      * then we need an unusual error code.  (But if we had to emulate
      * O_NOFOLLOW then the test already happened long ago.) */
-    if((flags & SSH_FXF_NOFOLLOW)
-       && (errno == ENOENT || errno == EEXIST)) {
+    if((flags & SSH_FXF_NOFOLLOW) && (errno == ENOENT || errno == EEXIST)) {
       if(lstat(path, &sb) < 0)
         return HANDLER_ERRNO;
       if(S_ISLNK(sb.st_mode))
@@ -289,7 +286,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
     return HANDLER_ERRNO;
   }
   /* Set initial attributrs if we created the file */
-  if(created && attrs->valid && (rc = sftp_set_fstatus(job->a, fd, attrs, 0))) { 
+  if(created && attrs->valid && (rc = sftp_set_fstatus(job->a, fd, attrs, 0))) {
     const int save_errno = errno;
     close(fd);
     unlink(path);
@@ -304,7 +301,7 @@ uint32_t sftp_generic_open(struct sftpjob *job, const char *path,
     unlink(path);
   }
   sftp_handle_new_file(&id, fd, path, sftp_handle_flags);
-  D(("...handle is %"PRIu32" %"PRIu32, id.id, id.tag));
+  D(("...handle is %" PRIu32 " %" PRIu32, id.id, id.tag));
   sftp_send_begin(job->worker);
   sftp_send_uint8(job->worker, SSH_FXP_HANDLE);
   sftp_send_uint32(job->worker, job->id);
@@ -322,9 +319,9 @@ uint32_t sftp_v56_rename(struct sftpjob *job) {
   pcheck(sftp_parse_path(job, &oldpath));
   pcheck(sftp_parse_path(job, &newpath));
   pcheck(sftp_parse_uint32(job, &flags));
-  D(("sftp_v56_rename %s %s %#"PRIx32, oldpath, newpath, flags));
+  D(("sftp_v56_rename %s %s %#" PRIx32, oldpath, newpath, flags));
 
-  if(flags & (SSH_FXF_RENAME_NATIVE|SSH_FXF_RENAME_OVERWRITE)) {
+  if(flags & (SSH_FXF_RENAME_NATIVE | SSH_FXF_RENAME_OVERWRITE)) {
     /* We asked for an overwriting rename (or a native one, in which case we're
      * allowed to do any old thing).  We are guaranteed that rename() is atomic
      * in the required sense on UNIX systems ("In this case, a link named new
@@ -343,17 +340,17 @@ uint32_t sftp_v56_rename(struct sftpjob *job) {
 #ifndef __linux__
         {
           struct stat sb;
-          
+
           if(lstat(newpath, &sb) == 0)
             return SSH_FX_FILE_ALREADY_EXISTS;
         }
 #endif
-	if(rename(oldpath, newpath) < 0)
-	  return HANDLER_ERRNO;
-	else
-	  return SSH_FX_OK;
+        if(rename(oldpath, newpath) < 0)
+          return HANDLER_ERRNO;
+        else
+          return SSH_FX_OK;
       } else
-	return SSH_FX_FILE_ALREADY_EXISTS;
+        return SSH_FX_FILE_ALREADY_EXISTS;
     } else if(unlink(oldpath) < 0) {
       const int save_errno = errno;
 
@@ -388,17 +385,17 @@ uint32_t sftp_vany_text_seek(struct sftpjob *job) {
   }
   /* Look for the right line */
   i = 0;
-  n = 0;                                /* quieten compiler */
-  D(("on entry: line=%"PRIu64, line));
+  n = 0; /* quieten compiler */
+  D(("on entry: line=%" PRIu64, line));
   while(line > 0 && (n = read(fd, buffer, sizeof buffer)) > 0) {
-    D(("outer: line=%"PRIu64" n=%zd", line, n));
+    D(("outer: line=%" PRIu64 " n=%zd", line, n));
     i = 0;
     while(line > 0 && i < n) {
       if(buffer[i++] == '\n')
-	--line;
+        --line;
     }
   }
-  D(("exited:: line=%"PRIu64" n=%zd i=%zd", line, n, i));
+  D(("exited:: line=%" PRIu64 " n=%zd i=%zd", line, n, i));
   if(n < 0)
     return HANDLER_ERRNO;
   else if(n == 0)
@@ -444,8 +441,9 @@ uint32_t sftp_vany_extended(struct sftpjob *job) {
   D(("extension %s", name));
   /* TODO when we have nontrivially many extensions we should use a binary
    * search here. */
-  for(n = 0; (n < protocol->nextensions
-	      && strcmp(name, protocol->extensions[n].name)); ++n)
+  for(n = 0;
+      (n < protocol->nextensions && strcmp(name, protocol->extensions[n].name));
+      ++n)
     ;
   if(n >= protocol->nextensions)
     return SSH_FX_OP_UNSUPPORTED;
@@ -454,59 +452,55 @@ uint32_t sftp_vany_extended(struct sftpjob *job) {
 }
 
 static const struct sftpcmd sftpv5tab[] = {
-  { SSH_FXP_INIT, sftp_vany_already_init },
-  { SSH_FXP_OPEN, sftp_v56_open },
-  { SSH_FXP_CLOSE, sftp_vany_close },
-  { SSH_FXP_READ, sftp_vany_read },
-  { SSH_FXP_WRITE, sftp_vany_write },
-  { SSH_FXP_LSTAT, sftp_v456_lstat },
-  { SSH_FXP_FSTAT, sftp_v456_fstat },
-  { SSH_FXP_SETSTAT, sftp_vany_setstat },
-  { SSH_FXP_FSETSTAT, sftp_vany_fsetstat },
-  { SSH_FXP_OPENDIR, sftp_vany_opendir },
-  { SSH_FXP_READDIR, sftp_vany_readdir },
-  { SSH_FXP_REMOVE, sftp_vany_remove },
-  { SSH_FXP_MKDIR, sftp_vany_mkdir },
-  { SSH_FXP_RMDIR, sftp_vany_rmdir },
-  { SSH_FXP_REALPATH, sftp_v345_realpath },
-  { SSH_FXP_STAT, sftp_v456_stat },
-  { SSH_FXP_RENAME, sftp_v56_rename },
-  { SSH_FXP_READLINK, sftp_vany_readlink },
-  { SSH_FXP_SYMLINK, sftp_v345_symlink },
-  { SSH_FXP_EXTENDED, sftp_vany_extended }
-};
+    {SSH_FXP_INIT, sftp_vany_already_init},
+    {SSH_FXP_OPEN, sftp_v56_open},
+    {SSH_FXP_CLOSE, sftp_vany_close},
+    {SSH_FXP_READ, sftp_vany_read},
+    {SSH_FXP_WRITE, sftp_vany_write},
+    {SSH_FXP_LSTAT, sftp_v456_lstat},
+    {SSH_FXP_FSTAT, sftp_v456_fstat},
+    {SSH_FXP_SETSTAT, sftp_vany_setstat},
+    {SSH_FXP_FSETSTAT, sftp_vany_fsetstat},
+    {SSH_FXP_OPENDIR, sftp_vany_opendir},
+    {SSH_FXP_READDIR, sftp_vany_readdir},
+    {SSH_FXP_REMOVE, sftp_vany_remove},
+    {SSH_FXP_MKDIR, sftp_vany_mkdir},
+    {SSH_FXP_RMDIR, sftp_vany_rmdir},
+    {SSH_FXP_REALPATH, sftp_v345_realpath},
+    {SSH_FXP_STAT, sftp_v456_stat},
+    {SSH_FXP_RENAME, sftp_v56_rename},
+    {SSH_FXP_READLINK, sftp_vany_readlink},
+    {SSH_FXP_SYMLINK, sftp_v345_symlink},
+    {SSH_FXP_EXTENDED, sftp_vany_extended}};
 
 static const struct sftpextension sftp_v5_extensions[] = {
-  { "fsync@openssh.com", "1", sftp_vany_fsync },
-  { "hardlink@openssh.com", "1", sftp_vany_hardlink },
-  { "posix-rename@openssh.com", "1", sftp_vany_posix_rename },
-  { "posix-rename@openssh.org", "", sftp_vany_posix_rename },
-  { "space-available", "", sftp_vany_space_available },
-  { "statfs@openssh.org", "", sftp_vany_statfs },
-  { "text-seek", "", sftp_vany_text_seek },
-  { "statvfs@openssh.com", "2", sftp_vany_statvfs },
-  { "fstatvfs@openssh.com", "2", sftp_vany_fstatvfs },
+    {"fsync@openssh.com", "1", sftp_vany_fsync},
+    {"hardlink@openssh.com", "1", sftp_vany_hardlink},
+    {"posix-rename@openssh.com", "1", sftp_vany_posix_rename},
+    {"posix-rename@openssh.org", "", sftp_vany_posix_rename},
+    {"space-available", "", sftp_vany_space_available},
+    {"statfs@openssh.org", "", sftp_vany_statfs},
+    {"text-seek", "", sftp_vany_text_seek},
+    {"statvfs@openssh.com", "2", sftp_vany_statvfs},
+    {"fstatvfs@openssh.com", "2", sftp_vany_fstatvfs},
 };
 
 const struct sftpprotocol sftp_v5 = {
-  sizeof sftpv5tab / sizeof (struct sftpcmd),
-  sftpv5tab,
-  5,
-  (SSH_FILEXFER_ATTR_SIZE
-   |SSH_FILEXFER_ATTR_PERMISSIONS
-   |SSH_FILEXFER_ATTR_ACCESSTIME
-   |SSH_FILEXFER_ATTR_MODIFYTIME
-   |SSH_FILEXFER_ATTR_OWNERGROUP
-   |SSH_FILEXFER_ATTR_SUBSECOND_TIMES
-   |SSH_FILEXFER_ATTR_BITS),
-  SSH_FX_LOCK_CONFLICT,
-  sftp_v456_sendnames,
-  sftp_v456_sendattrs,
-  sftp_v456_parseattrs,
-  sftp_v456_encode,
-  sftp_v456_decode,
-  sizeof sftp_v5_extensions / sizeof (struct sftpextension),
-  sftp_v5_extensions,
+    sizeof sftpv5tab / sizeof(struct sftpcmd),
+    sftpv5tab,
+    5,
+    (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+     SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
+     SSH_FILEXFER_ATTR_OWNERGROUP | SSH_FILEXFER_ATTR_SUBSECOND_TIMES |
+     SSH_FILEXFER_ATTR_BITS),
+    SSH_FX_LOCK_CONFLICT,
+    sftp_v456_sendnames,
+    sftp_v456_sendattrs,
+    sftp_v456_parseattrs,
+    sftp_v456_encode,
+    sftp_v456_decode,
+    sizeof sftp_v5_extensions / sizeof(struct sftpextension),
+    sftp_v5_extensions,
 };
 
 /*
diff --git a/v6.c b/v6.c
index 3ca6acb..e557bed 100644
--- a/v6.c
+++ b/v6.c
@@ -28,6 +28,7 @@
 #include "debug.h"
 #include "utils.h"
 #include "globals.h"
+#include "queue.h"
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
@@ -69,7 +70,7 @@ uint32_t sftp_v6_realpath(struct sftpjob *job) {
     break;
   case SSH_FXP_REALPATH_STAT_ALWAYS:
     /* Follow links and fail if the path doesn't exist */
-    rpflags = RP_READLINK|RP_MUST_EXIST;
+    rpflags = RP_READLINK | RP_MUST_EXIST;
     break;
   default:
     return SSH_FX_BAD_MESSAGE;
@@ -80,7 +81,7 @@ uint32_t sftp_v6_realpath(struct sftpjob *job) {
   switch(control_byte) {
   case SSH_FXP_REALPATH_NO_CHECK:
     /* Don't stat, send dummy attributes */
-    memset(&attrs, 0, sizeof attrs);
+    sftp_memset(&attrs, 0, sizeof attrs);
     attrs.name = resolvedpath;
     break;
   case SSH_FXP_REALPATH_STAT_IF:
@@ -88,7 +89,7 @@ uint32_t sftp_v6_realpath(struct sftpjob *job) {
     if(stat(resolvedpath, &sb) >= 0 || lstat(resolvedpath, &sb) >= 0)
       sftp_stat_to_attrs(job->a, &sb, &attrs, 0xFFFFFFFF, resolvedpath);
     else {
-      memset(&attrs, 0, sizeof attrs);
+      sftp_memset(&attrs, 0, sizeof attrs);
       attrs.name = resolvedpath;
     }
     break;
@@ -118,7 +119,8 @@ uint32_t sftp_v6_link(struct sftpjob *job) {
   if(readonly)
     return SSH_FX_PERMISSION_DENIED;
   pcheck(sftp_parse_path(job, &newlinkpath));
-  pcheck(sftp_parse_string(job, &oldpath, 0));    /* aka existing-path/target-paths */
+  pcheck(
+      sftp_parse_string(job, &oldpath, 0)); /* aka existing-path/target-paths */
   pcheck(sftp_parse_uint8(job, &symbolic));
   D(("sftp_link %s %s [%s]", oldpath, newlinkpath,
      symbolic ? "symbolic" : "hard"));
@@ -156,76 +158,85 @@ uint32_t sftp_v6_version_select(struct sftpjob *job) {
   if(!workqueue) {
     pcheck(sftp_parse_path(job, &newversion));
     /* Handle known versions */
-    if(!strcmp(newversion, "3")) { protocol = &sftp_v3; return SSH_FX_OK; }
-    if(!strcmp(newversion, "4")) { protocol = &sftp_v4; return SSH_FX_OK; }
-    if(!strcmp(newversion, "5")) { protocol = &sftp_v5; return SSH_FX_OK; }
-    if(!strcmp(newversion, "6")) { protocol = &sftp_v6; return SSH_FX_OK; }
+    if(!strcmp(newversion, "3")) {
+      protocol = &sftp_v3;
+      return SSH_FX_OK;
+    }
+    if(!strcmp(newversion, "4")) {
+      protocol = &sftp_v4;
+      return SSH_FX_OK;
+    }
+    if(!strcmp(newversion, "5")) {
+      protocol = &sftp_v5;
+      return SSH_FX_OK;
+    }
+    if(!strcmp(newversion, "6")) {
+      protocol = &sftp_v6;
+      return SSH_FX_OK;
+    }
     sftp_send_status(job, SSH_FX_INVALID_PARAMETER, "unknown version");
   } else
-    sftp_send_status(job, SSH_FX_INVALID_PARAMETER, "badly timed version-select");
+    sftp_send_status(job, SSH_FX_INVALID_PARAMETER,
+                     "badly timed version-select");
   /* We MUST close the channel.  (-13, s5.5). */
-  exit(-1);
+  sftp_state_set(sftp_state_stop);
+  return HANDLER_RESPONDED; /* even though we sent nothing */
 }
 
 static const struct sftpcmd sftpv6tab[] = {
-  { SSH_FXP_INIT, sftp_vany_already_init },
-  { SSH_FXP_OPEN, sftp_v56_open },
-  { SSH_FXP_CLOSE, sftp_vany_close },
-  { SSH_FXP_READ, sftp_vany_read },
-  { SSH_FXP_WRITE, sftp_vany_write },
-  { SSH_FXP_LSTAT, sftp_v456_lstat },
-  { SSH_FXP_FSTAT, sftp_v456_fstat },
-  { SSH_FXP_SETSTAT, sftp_vany_setstat },
-  { SSH_FXP_FSETSTAT, sftp_vany_fsetstat },
-  { SSH_FXP_OPENDIR, sftp_vany_opendir },
-  { SSH_FXP_READDIR, sftp_vany_readdir },
-  { SSH_FXP_REMOVE, sftp_vany_remove },
-  { SSH_FXP_MKDIR, sftp_vany_mkdir },
-  { SSH_FXP_RMDIR, sftp_vany_rmdir },
-  { SSH_FXP_REALPATH, sftp_v6_realpath },
-  { SSH_FXP_STAT, sftp_v456_stat },
-  { SSH_FXP_RENAME, sftp_v56_rename },
-  { SSH_FXP_READLINK, sftp_vany_readlink },
-  { SSH_FXP_LINK, sftp_v6_link },
-  { SSH_FXP_EXTENDED, sftp_vany_extended }
-};
+    {SSH_FXP_INIT, sftp_vany_already_init},
+    {SSH_FXP_OPEN, sftp_v56_open},
+    {SSH_FXP_CLOSE, sftp_vany_close},
+    {SSH_FXP_READ, sftp_vany_read},
+    {SSH_FXP_WRITE, sftp_vany_write},
+    {SSH_FXP_LSTAT, sftp_v456_lstat},
+    {SSH_FXP_FSTAT, sftp_v456_fstat},
+    {SSH_FXP_SETSTAT, sftp_vany_setstat},
+    {SSH_FXP_FSETSTAT, sftp_vany_fsetstat},
+    {SSH_FXP_OPENDIR, sftp_vany_opendir},
+    {SSH_FXP_READDIR, sftp_vany_readdir},
+    {SSH_FXP_REMOVE, sftp_vany_remove},
+    {SSH_FXP_MKDIR, sftp_vany_mkdir},
+    {SSH_FXP_RMDIR, sftp_vany_rmdir},
+    {SSH_FXP_REALPATH, sftp_v6_realpath},
+    {SSH_FXP_STAT, sftp_v456_stat},
+    {SSH_FXP_RENAME, sftp_v56_rename},
+    {SSH_FXP_READLINK, sftp_vany_readlink},
+    {SSH_FXP_LINK, sftp_v6_link},
+    {SSH_FXP_EXTENDED, sftp_vany_extended}};
 
 /* TODO: file locking */
 
 static const struct sftpextension sftp_v6_extensions[] = {
-  { "fsync@openssh.com", "1", sftp_vany_fsync },
-  { "hardlink@openssh.com", "1", sftp_vany_hardlink },
-  { "posix-rename@openssh.com", "1", sftp_vany_posix_rename },
-  { "posix-rename@openssh.org", "", sftp_vany_posix_rename },
-  { "space-available", "", sftp_vany_space_available },
-  { "statfs@openssh.org", "", sftp_vany_statfs },
-  { "text-seek", "", sftp_vany_text_seek },
-  { "version-select", "", sftp_v6_version_select },
-  { "statvfs@openssh.com", "2", sftp_vany_statvfs },
-  { "fstatvfs@openssh.com", "2", sftp_vany_fstatvfs },
+    {"fsync@openssh.com", "1", sftp_vany_fsync},
+    {"hardlink@openssh.com", "1", sftp_vany_hardlink},
+    {"posix-rename@openssh.com", "1", sftp_vany_posix_rename},
+    {"posix-rename@openssh.org", "", sftp_vany_posix_rename},
+    {"space-available", "", sftp_vany_space_available},
+    {"statfs@openssh.org", "", sftp_vany_statfs},
+    {"text-seek", "", sftp_vany_text_seek},
+    {"version-select", "", sftp_v6_version_select},
+    {"statvfs@openssh.com", "2", sftp_vany_statvfs},
+    {"fstatvfs@openssh.com", "2", sftp_vany_fstatvfs},
 };
 
 const struct sftpprotocol sftp_v6 = {
-  sizeof sftpv6tab / sizeof (struct sftpcmd),
-  sftpv6tab,
-  6,
-  (SSH_FILEXFER_ATTR_SIZE
-   |SSH_FILEXFER_ATTR_PERMISSIONS
-   |SSH_FILEXFER_ATTR_ACCESSTIME
-   |SSH_FILEXFER_ATTR_CTIME
-   |SSH_FILEXFER_ATTR_MODIFYTIME
-   |SSH_FILEXFER_ATTR_OWNERGROUP
-   |SSH_FILEXFER_ATTR_SUBSECOND_TIMES
-   |SSH_FILEXFER_ATTR_BITS
-   |SSH_FILEXFER_ATTR_LINK_COUNT),
-  SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK,
-  sftp_v456_sendnames,
-  sftp_v456_sendattrs,
-  sftp_v456_parseattrs,
-  sftp_v456_encode,
-  sftp_v456_decode,
-  sizeof sftp_v6_extensions / sizeof (struct sftpextension),
-  sftp_v6_extensions,
+    sizeof sftpv6tab / sizeof(struct sftpcmd),
+    sftpv6tab,
+    6,
+    (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_PERMISSIONS |
+     SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_CTIME |
+     SSH_FILEXFER_ATTR_MODIFYTIME | SSH_FILEXFER_ATTR_OWNERGROUP |
+     SSH_FILEXFER_ATTR_SUBSECOND_TIMES | SSH_FILEXFER_ATTR_BITS |
+     SSH_FILEXFER_ATTR_LINK_COUNT),
+    SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK,
+    sftp_v456_sendnames,
+    sftp_v456_sendattrs,
+    sftp_v456_parseattrs,
+    sftp_v456_encode,
+    sftp_v456_decode,
+    sizeof sftp_v6_extensions / sizeof(struct sftpextension),
+    sftp_v6_extensions,
 };
 
 /*
diff --git a/xfns.c b/xfns.c
index 014c0c2..0b4d2e1 100644
--- a/xfns.c
+++ b/xfns.c
@@ -27,22 +27,22 @@
 #include <stdarg.h>
 #include <stdio.h>
 
-void xclose(int fd) {
+void sftp_xclose(int fd) {
   if(close(fd) < 0)
-    fatal("error calling close: %s", strerror(errno));
+    sftp_fatal("error calling close: %s", strerror(errno));
 }
 
-void xdup2(int fd, int newfd) {
+void sftp_xdup2(int fd, int newfd) {
   if(dup2(fd, newfd) < 0)
-    fatal("error calling dup2: %s", strerror(errno));
+    sftp_fatal("error calling dup2: %s", strerror(errno));
 }
 
-void xpipe(int *pfd) {
+void sftp_xpipe(int *pfd) {
   if(pipe(pfd) < 0)
-    fatal("error calling pipe: %s", strerror(errno));
+    sftp_fatal("error calling pipe: %s", strerror(errno));
 }
 
-int xprintf(const char *fmt, ...) {
+int sftp_xprintf(const char *fmt, ...) {
   va_list ap;
   int rc;
 
@@ -50,7 +50,7 @@ int xprintf(const char *fmt, ...) {
   rc = vfprintf(stdout, fmt, ap);
   va_end(ap);
   if(rc < 0)
-    fatal("error writing to stdout: %s", strerror(errno));
+    sftp_fatal("error writing to stdout: %s", strerror(errno));
   return rc;
 }
 
diff --git a/xfns.h b/xfns.h
index f53d929..3d84c3e 100644
--- a/xfns.h
+++ b/xfns.h
@@ -21,38 +21,38 @@
 /** @file xfns.h @brief Die-on-error utility function interface */
 
 #ifndef XFNS_H
-#define XFNS_H
+#  define XFNS_H
 
 /** @brief Close @p fd
  * @param fd File descriptor to close
  *
- * Calls fatal() on error.
+ * Calls sftp_fatal() on error.
  */
-void xclose(int fd);
+void sftp_xclose(int fd);
 
 /** @brief Duplicate @p fd
  * @param fd File descriptor to duplicate
  * @param newfd New file descriptor
  *
- * Calls fatal() on error.
+ * Calls sftp_fatal() on error.
  */
-void xdup2(int fd, int newfd);
+void sftp_xdup2(int fd, int newfd);
 
 /** @brief Create a pipe
  * @param pfd Where to store endpoint file descriptors
  *
- * Calls fatal() on error.
+ * Calls sftp_fatal() on error.
  */
-void xpipe(int *pfd);
+void sftp_xpipe(int *pfd);
 
 /** @brief Write to stdout
  * @param fmt Format string as per @c printf()
  * @param ... Arguments
  * @return Number of characters written
  *
- * Calls fatal() on error.
+ * Calls sftp_fatal() on error.
  */
-int xprintf(const char *fmt, ...) attribute((format(printf,1,2)));
+int sftp_xprintf(const char *fmt, ...) attribute((format(printf, 1, 2)));
 
 #endif /* XFNS_H */
 

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/lib/debug/.build-id/c9/ad725ee72e62c80fa42516aad68ea57ff99fd3.debug

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/lib/debug/.build-id/f5/2772528a302cf8099f74d9339c045178bf346a.debug

No differences were encountered between the control files of package gesftpserver

Control files of package gesftpserver-dbgsym: lines which differ (wdiff format)

  • Build-Ids: f52772528a302cf8099f74d9339c045178bf346a c9ad725ee72e62c80fa42516aad68ea57ff99fd3

Run locally

More details

Full run details