On Tue, 11 Jul 2017 at 15:00:02 +0100, Colin Watson wrote:
> On Mon, Jul 10, 2017 at 09:55:15PM +0300, Guilhem Moulin wrote:
>> Meanwhile I had a look at dropbear's scp variant and AFAICT it's
>> actually an almost exact copy of OpenSSH 4.3p2's.  (It's mentioned in
>> the headers, and the diff is pretty minimal.)
> 
> Could you attach the diff?

Attached.

-- 
Guilhem.
diff -u a/scp.c b/scp.c
--- a/scp.c
+++ b/scp.c
@@ -1,3 +1,6 @@
+/* Dropbear Note: This file is based on OpenSSH 4.3p2. Avoid unnecessary 
+   changes to simplify future updates */
+
 /*
  * scp - secure remote copy.  This is basically patched BSD rcp which
  * uses ssh to do the data transfer (instead of using rcmd).
@@ -71,17 +74,13 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: scp.c,v 1.130 2006/01/31 10:35:43 djm Exp $");
+/*RCSID("$OpenBSD: scp.c,v 1.130 2006/01/31 10:35:43 djm Exp $");*/
 
-#include "xmalloc.h"
 #include "atomicio.h"
-#include "pathnames.h"
-#include "log.h"
-#include "misc.h"
+#include "compat.h"
+#include "scpmisc.h"
 #include "progressmeter.h"
 
-extern char *__progname;
-
 void bwlimit(int);
 
 /* Struct for addargs */
@@ -100,7 +99,7 @@
 int showprogress = 1;
 
 /* This is the program to execute for the secured connection. ("ssh" or -S) */
-char *ssh_program = _PATH_SSH_PROGRAM;
+char *ssh_program = DROPBEAR_PATH_SSH_PROGRAM;
 
 /* This is used to store the pid of ssh_program */
 pid_t do_cmd_pid = -1;
@@ -134,13 +133,22 @@
                        fprintf(stderr, " %s", a->list[i]);
                fprintf(stderr, "\n");
        }
-       if ((pid = fork()) == -1)
+#ifdef USE_VFORK
+       pid = vfork();
+#else
+       pid = fork();
+#endif
+       if (pid == -1)
                fatal("do_local_cmd: fork: %s", strerror(errno));
 
        if (pid == 0) {
                execvp(a->list[0], a->list);
                perror(a->list[0]);
+#ifdef USE_VFORK
+               _exit(1);
+#else
                exit(1);
+#endif
        }
 
        do_cmd_pid = pid;
@@ -166,6 +174,16 @@
  * assigns the input and output file descriptors on success.
  */
 
+static void
+arg_setup(char *host, char *remuser, char *cmd)
+{
+       replacearg(&args, 0, "%s", ssh_program);
+       if (remuser != NULL)
+               addargs(&args, "-l%s", remuser);
+       addargs(&args, "%s", host);
+       addargs(&args, "%s", cmd);
+}
+
 int
 do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
 {
@@ -193,8 +211,19 @@
        close(reserved[0]);
        close(reserved[1]);
 
+       /* uClinux needs to build the args here before vforking,
+          otherwise we do it later on. */
+#ifdef USE_VFORK
+       arg_setup(host, remuser, cmd);
+#endif
+
        /* Fork a child to execute the command on the remote host using ssh. */
+#ifdef USE_VFORK
+       do_cmd_pid = vfork();
+#else
        do_cmd_pid = fork();
+#endif
+
        if (do_cmd_pid == 0) {
                /* Child. */
                close(pin[1]);
@@ -204,18 +233,39 @@
                close(pin[0]);
                close(pout[1]);
 
-               replacearg(&args, 0, "%s", ssh_program);
-               if (remuser != NULL)
-                       addargs(&args, "-l%s", remuser);
-               addargs(&args, "%s", host);
-               addargs(&args, "%s", cmd);
+#ifndef USE_VFORK
+               arg_setup(host, remuser, cmd);
+#endif
 
                execvp(ssh_program, args.list);
                perror(ssh_program);
+#ifdef USE_VFORK
+               _exit(1);
+#else
                exit(1);
+#endif
        } else if (do_cmd_pid == -1) {
                fatal("fork: %s", strerror(errno));
        }
+
+#ifdef USE_VFORK
+       /* clean up command */
+       /* pop cmd */
+       xfree(args.list[args.num-1]);
+       args.list[args.num-1]=NULL;
+       args.num--;
+       /* pop host */
+       xfree(args.list[args.num-1]);
+       args.list[args.num-1]=NULL;
+       args.num--;
+       /* pop user */
+       if (remuser != NULL) {
+               xfree(args.list[args.num-1]);
+               args.list[args.num-1]=NULL;
+               args.num--;
+       }
+#endif
+
        /* Parent.  Close the other side, and return the local side. */
        close(pin[0]);
        *fdout = pin[1];
@@ -239,7 +289,6 @@
 void run_err(const char *,...);
 void verifydir(char *);
 
-struct passwd *pwd;
 uid_t userid;
 int errs, remin, remout;
 int pflag, iamremote, iamrecursive, targetshouldbedirectory;
@@ -255,8 +304,13 @@
 void toremote(char *, int, char *[]);
 void usage(void);
 
+#if defined(DBMULTI_scp) || !defined(DROPBEAR_MULTI)
+#if defined(DBMULTI_scp) && defined(DROPBEAR_MULTI)
+int scp_main(int argc, char **argv)
+#else
 int
 main(int argc, char **argv)
+#endif
 {
        int ch, fflag, tflag, status;
        double speed;
@@ -267,15 +321,9 @@
        /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
        sanitise_stdfd();
 
-       __progname = ssh_get_progname(argv[0]);
-
        memset(&args, '\0', sizeof(args));
        args.list = NULL;
        addargs(&args, "%s", ssh_program);
-       addargs(&args, "-x");
-       addargs(&args, "-oForwardAgent no");
-       addargs(&args, "-oPermitLocalCommand no");
-       addargs(&args, "-oClearAllForwardings yes");
 
        fflag = tflag = 0;
        while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1)
@@ -298,7 +346,7 @@
                        addargs(&args, "-p%s", optarg);
                        break;
                case 'B':
-                       addargs(&args, "-oBatchmode yes");
+                       fprintf(stderr, "Note: -B option is disabled in this 
version of scp");
                        break;
                case 'l':
                        speed = strtod(optarg, &endp);
@@ -320,8 +368,10 @@
                        verbose_mode = 1;
                        break;
                case 'q':
+#ifdef PROGRESS_METER
                        addargs(&args, "-q");
                        showprogress = 0;
+#endif
                        break;
 
                /* Server options. */
@@ -345,9 +395,6 @@
        argc -= optind;
        argv += optind;
 
-       if ((pwd = getpwuid(userid = getuid())) == NULL)
-               fatal("unknown user %u", (u_int) userid);
-
        if (!isatty(STDERR_FILENO))
                showprogress = 0;
 
@@ -389,13 +436,13 @@
        }
        /*
         * Finally check the exit status of the ssh process, if one was forked
-        * and no error has occured yet
+        * and no error has occurred yet
         */
        if (do_cmd_pid != -1 && errs == 0) {
                if (remin != -1)
-                   (void) close(remin);
+                       (void) close(remin);
                if (remout != -1)
-                   (void) close(remout);
+                       (void) close(remout);
                if (waitpid(do_cmd_pid, &status, 0) == -1)
                        errs = 1;
                else {
@@ -405,6 +452,7 @@
        }
        exit(errs != 0);
 }
+#endif /* DBMULTI_scp stuff */
 
 void
 toremote(char *targ, int argc, char **argv)
@@ -444,9 +492,13 @@
                        addargs(&alist, "%s", ssh_program);
                        if (verbose_mode)
                                addargs(&alist, "-v");
+#if 0
+                       /* Disabled since dbclient won't understand them
+                          and scp works fine without them. */
                        addargs(&alist, "-x");
                        addargs(&alist, "-oClearAllForwardings yes");
                        addargs(&alist, "-n");
+#endif
 
                        *src++ = 0;
                        if (*src == 0)
@@ -458,7 +510,7 @@
                                host = cleanhostname(host);
                                suser = argv[i];
                                if (*suser == '\0')
-                                       suser = pwd->pw_name;
+                                       continue; /* pretend there wasn't any @ 
at all */
                                else if (!okname(suser))
                                        continue;
                                addargs(&alist, "-l");
@@ -526,7 +578,7 @@
                        *host++ = 0;
                        suser = argv[i];
                        if (*suser == '\0')
-                               suser = pwd->pw_name;
+                               suser = NULL;
                }
                host = cleanhostname(host);
                len = strlen(src) + CMDNEEDS + 20;
@@ -620,8 +672,10 @@
                        }
                        continue;
                }
+#ifdef PROGRESS_METER
                if (showprogress)
                        start_progress_meter(curfile, stb.st_size, &statbytes);
+#endif
                /* Keep writing after an error so that we stay sync'd up. */
                for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
                        amt = bp->cnt;
@@ -643,8 +697,10 @@
                        if (limit_rate)
                                bwlimit(amt);
                }
+#ifdef PROGRESS_METER
                if (showprogress)
                        stop_progress_meter();
+#endif
 
                if (fd != -1) {
                        if (close(fd) < 0 && !haderr)
@@ -716,8 +772,8 @@
 bwlimit(int amount)
 {
        static struct timeval bwstart, bwend;
-       static int lamt, thresh = 16384;
-       u_int64_t waitlen;
+       static int lamt = 0, thresh = 16384;
+       uint64_t waitlen;
        struct timespec ts, rm;
 
        if (!timerisset(&bwstart)) {
@@ -785,7 +841,7 @@
 
 #define        atime   tv[0]
 #define        mtime   tv[1]
-#define        SCREWUP(str)    { why = str; goto screwup; }
+#define        SCREWUP(str)    do { why = str; goto screwup; } while (0)
 
        setimes = targisdir = 0;
        mask = umask(0);
@@ -884,8 +940,8 @@
                        exit(1);
                }
                if (targisdir) {
-                       static char *namebuf;
-                       static size_t cursize;
+                       static char *namebuf = NULL;
+                       static size_t cursize = 0;
                        size_t need;
 
                        need = strlen(targ) + strlen(cp) + 250;
@@ -935,7 +991,7 @@
                        continue;
                }
                omode = mode;
-               mode |= S_IWRITE;
+               mode |= S_IWUSR;
                if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
 bad:                   run_err("%s: %s", np, strerror(errno));
                        continue;
@@ -949,8 +1005,10 @@
                wrerr = NO;
 
                statbytes = 0;
+#ifdef PROGRESS_METER
                if (showprogress)
                        start_progress_meter(curfile, size, &statbytes);
+#endif
                for (count = i = 0; i < size; i += 4096) {
                        amt = 4096;
                        if (i + amt > size)
@@ -984,8 +1042,10 @@
                                cp = bp->buf;
                        }
                }
+#ifdef PROGRESS_METER
                if (showprogress)
                        stop_progress_meter();
+#endif
                if (count != 0 && wrerr == NO &&
                    atomicio(vwrite, ofd, bp->buf, count) != count) {
                        wrerr = YES;
@@ -1085,7 +1145,7 @@
 {
        (void) fprintf(stderr,
            "usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i 
identity_file]\n"
-           "           [-l limit] [-o ssh_option] [-P port] [-S program]\n"
+           "           [-l limit] [-P port] [-S program]\n"
            "           [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
        exit(1);
 }
@@ -1093,7 +1153,7 @@
 void
 run_err(const char *fmt,...)
 {
-       static FILE *fp;
+       static FILE *fp = NULL;
        va_list ap;
 
        ++errs;
diff -u a/atomicio.h b/atomicio.h
--- a/atomicio.h
+++ b/atomicio.h
@@ -1,6 +1,9 @@
-/*     $OpenBSD: atomicio.h,v 1.6 2005/05/24 17:32:43 avsm Exp $       */
 
 /*
+ * Copied from OpenSSH 3.6.1p2, required for loginrec.c
+ *
+ * $OpenBSD: atomicio.h,v 1.4 2001/06/26 06:32:46 itojun Exp $
+ *
  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
  * All rights reserved.
  *
@@ -25,9 +28,9 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "includes.h"
+
 /*
- * Ensure all of data on socket comes through. f==read || f==vwrite
+ * Ensure all of data on socket comes through. f==read || f==write
  */
-size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
-
-#define vwrite (ssize_t (*)(int, void *, size_t))write
+ssize_t        atomicio(ssize_t (*)(), int, void *, size_t);
diff -u a/atomicio.c b/atomicio.c
--- a/atomicio.c
+++ b/atomicio.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
+ * Copied from OpenSSH 3.6.1p2.
+ * 
  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
  * All rights reserved.
  *
@@ -24,24 +25,23 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "includes.h"
-RCSID("$OpenBSD: atomicio.c,v 1.13 2005/05/24 17:32:43 avsm Exp $");
+/* RCSID("OpenBSD: atomicio.c,v 1.10 2001/05/08 22:48:07 markus Exp "); */
 
 #include "atomicio.h"
 
 /*
- * ensure all of data on socket comes through. f==read || f==vwrite
+ * ensure all of data on socket comes through. f==read || f==write
  */
-size_t
+ssize_t
 atomicio(f, fd, _s, n)
-       ssize_t (*f) (int, void *, size_t);
+       ssize_t (*f) ();
        int fd;
        void *_s;
        size_t n;
 {
        char *s = _s;
-       size_t pos = 0;
        ssize_t res;
+       size_t pos = 0;
 
        while (n > pos) {
                res = (f) (fd, s + pos, n - pos);
@@ -53,12 +53,11 @@
                        if (errno == EINTR || errno == EAGAIN)
 #endif
                                continue;
-                       return 0;
+                       /* FALLTHROUGH */
                case 0:
-                       errno = EPIPE;
-                       return pos;
+                       return (res);
                default:
-                       pos += (u_int)res;
+                       pos += res;
                }
        }
        return (pos);
diff -u a/misc.h b/scpmisc.h
--- a/misc.h
+++ b/scpmisc.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: misc.h,v 1.29 2006/01/31 10:19:02 djm Exp $   */
+/*     $OpenBSD: misc.h,v 1.12 2002/03/19 10:49:35 markus Exp $        */
 
 /*
  * Author: Tatu Ylonen <[email protected]>
@@ -12,58 +12,58 @@
  * called by a name other than "ssh" or "Secure Shell".
  */
 
-/* misc.c */
+/* actually from atomicio, but is only used in scp code */
+#define vwrite (ssize_t (*)(int, void *, size_t))write
 
 char   *chop(char *);
 char   *strdelim(char **);
-int     set_nonblock(int);
-int     unset_nonblock(int);
+void    set_nonblock(int);
+void    unset_nonblock(int);
 void    set_nodelay(int);
 int     a2port(const char *);
-int     a2tun(const char *, int *);
-char   *hpdelim(char **);
 char   *cleanhostname(char *);
 char   *colon(char *);
 long    convtime(const char *);
-char   *tilde_expand_filename(const char *, uid_t);
-char   *percent_expand(const char *, ...) __attribute__((__sentinel__));
-char   *tohex(const u_char *, u_int);
-void    sanitise_stdfd(void);
 
 struct passwd *pwcopy(struct passwd *);
 
 typedef struct arglist arglist;
 struct arglist {
        char    **list;
-       u_int   num;
-       u_int   nalloc;
+       int     num;
+       int     nalloc;
 };
-void    addargs(arglist *, char *, ...)
-            __attribute__((format(printf, 2, 3)));
-void    replacearg(arglist *, u_int, char *, ...)
-            __attribute__((format(printf, 3, 4)));
+void    addargs(arglist *, char *, ...);
+void    replacearg(arglist *, u_int, char *, ...);
 void    freeargs(arglist *);
 
-/* readpass.c */
+/* from xmalloc.h */
+void   *xmalloc(size_t);
+void   *xrealloc(void *, size_t);
+void     xfree(void *);
+char   *xstrdup(const char *);
+
+char *ssh_get_progname(char *);
+void fatal(char* fmt,...);
+void sanitise_stdfd(void);
+
+/* Required for non-BSD platforms, from OpenSSH's defines.h */
+#ifndef timersub
+#define timersub(a, b, result)                  \
+   do {                             \
+      (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;     \
+      (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;      \
+      if ((result)->tv_usec < 0) {              \
+     --(result)->tv_sec;                    \
+     (result)->tv_usec += 1000000;              \
+      }                             \
+   } while (0)
+#endif
+
+#ifndef TIMEVAL_TO_TIMESPEC
+#define TIMEVAL_TO_TIMESPEC(tv, ts) {                   \
+    (ts)->tv_sec = (tv)->tv_sec;                    \
+    (ts)->tv_nsec = (tv)->tv_usec * 1000;               \
+}
+#endif
 
-#define RP_ECHO                        0x0001
-#define RP_ALLOW_STDIN         0x0002
-#define RP_ALLOW_EOF           0x0004
-#define RP_USE_ASKPASS         0x0008
-
-char   *read_passphrase(const char *, int);
-int     ask_permission(const char *, ...) __attribute__((format(printf, 1, 
2)));
-int     read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
-
-int     tun_open(int, int);
-
-/* Common definitions for ssh tunnel device forwarding */
-#define SSH_TUNMODE_NO         0x00
-#define SSH_TUNMODE_POINTOPOINT        0x01
-#define SSH_TUNMODE_ETHERNET   0x02
-#define SSH_TUNMODE_DEFAULT    SSH_TUNMODE_POINTOPOINT
-#define SSH_TUNMODE_YES                
(SSH_TUNMODE_POINTOPOINT|SSH_TUNMODE_ETHERNET)
-
-#define SSH_TUNID_ANY          0x7fffffff
-#define SSH_TUNID_ERR          (SSH_TUNID_ANY - 1)
-#define SSH_TUNID_MAX          (SSH_TUNID_ANY - 2)
diff -u a/misc.c b/scpmisc.c
--- a/misc.c
+++ b/scpmisc.c
@@ -1,6 +1,8 @@
+/* Dropbear Note: This file is based on OpenSSH 4.3p2. Avoid unnecessary 
+   changes to simplify future updates */
+
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
- * Copyright (c) 2005 Damien Miller.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -23,334 +25,85 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "includes.h"
-RCSID("$OpenBSD: misc.c,v 1.42 2006/01/31 10:19:02 djm Exp $");
-
-#ifdef SSH_TUN_OPENBSD
-#include <net/if.h>
-#endif
+/*RCSID("OpenBSD: misc.c,v 1.22 2003/09/18 08:49:45 markus Exp ");*/
 
-#include "misc.h"
-#include "log.h"
-#include "xmalloc.h"
+/* For xmalloc, xfree etc:
+ * Author: Tatu Ylonen <[email protected]>
+ * Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
+ *                    All rights reserved
+ * Versions of malloc and friends that check their results, and never return
+ * failure (they call fatal if they encounter an error).
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
 
-/* remove newline at end of string */
-char *
-chop(char *s)
-{
-       char *t = s;
-       while (*t) {
-               if (*t == '\n' || *t == '\r') {
-                       *t = '\0';
-                       return s;
-               }
-               t++;
-       }
-       return s;
+/*RCSID("OpenBSD: xmalloc.c,v 1.16 2001/07/23 18:21:46 stevesk Exp ");*/
 
-}
+#define _GNU_SOURCE
+#include "includes.h"
+#include "scpmisc.h"
 
-/* set/unset filedescriptor to non-blocking */
-int
-set_nonblock(int fd)
+void *
+xmalloc(size_t size)
 {
-       int val;
+       void *ptr;
 
-       val = fcntl(fd, F_GETFL, 0);
-       if (val < 0) {
-               error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
-               return (-1);
-       }
-       if (val & O_NONBLOCK) {
-               debug3("fd %d is O_NONBLOCK", fd);
-               return (0);
+       if (size == 0) {
+               fprintf(stderr, "xmalloc: zero size\n");
+               exit(EXIT_FAILURE);
        }
-       debug2("fd %d setting O_NONBLOCK", fd);
-       val |= O_NONBLOCK;
-       if (fcntl(fd, F_SETFL, val) == -1) {
-               debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd,
-                   strerror(errno));
-               return (-1);
+       ptr = malloc(size);
+       if (ptr == NULL) {
+               fprintf(stderr, "xmalloc: out of memory (allocating %lu 
bytes)\n", (u_long) size);
+               exit(EXIT_FAILURE);
        }
-       return (0);
+       return ptr;
 }
 
-int
-unset_nonblock(int fd)
+void *
+xrealloc(void *ptr, size_t new_size)
 {
-       int val;
+       void *new_ptr;
 
-       val = fcntl(fd, F_GETFL, 0);
-       if (val < 0) {
-               error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
-               return (-1);
-       }
-       if (!(val & O_NONBLOCK)) {
-               debug3("fd %d is not O_NONBLOCK", fd);
-               return (0);
+       if (new_size == 0) {
+               fprintf(stderr, "xrealloc: zero size\n");
+               exit(EXIT_FAILURE);
        }
-       debug("fd %d clearing O_NONBLOCK", fd);
-       val &= ~O_NONBLOCK;
-       if (fcntl(fd, F_SETFL, val) == -1) {
-               debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s",
-                   fd, strerror(errno));
-               return (-1);
+       if (ptr == NULL)
+               new_ptr = malloc(new_size);
+       else
+               new_ptr = realloc(ptr, new_size);
+       if (new_ptr == NULL) {
+               fprintf(stderr, "xrealloc: out of memory (new_size %lu 
bytes)\n", (u_long) new_size);
+               exit(EXIT_FAILURE);
        }
-       return (0);
+       return new_ptr;
 }
 
-/* disable nagle on socket */
 void
-set_nodelay(int fd)
-{
-       int opt;
-       socklen_t optlen;
-
-       optlen = sizeof opt;
-       if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
-               debug("getsockopt TCP_NODELAY: %.100s", strerror(errno));
-               return;
-       }
-       if (opt == 1) {
-               debug2("fd %d is TCP_NODELAY", fd);
-               return;
-       }
-       opt = 1;
-       debug2("fd %d setting TCP_NODELAY", fd);
-       if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
-               error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
-}
-
-/* Characters considered whitespace in strsep calls. */
-#define WHITESPACE " \t\r\n"
-
-/* return next token in configuration line */
-char *
-strdelim(char **s)
-{
-       char *old;
-       int wspace = 0;
-
-       if (*s == NULL)
-               return NULL;
-
-       old = *s;
-
-       *s = strpbrk(*s, WHITESPACE "=");
-       if (*s == NULL)
-               return (old);
-
-       /* Allow only one '=' to be skipped */
-       if (*s[0] == '=')
-               wspace = 1;
-       *s[0] = '\0';
-
-       *s += strspn(*s + 1, WHITESPACE) + 1;
-       if (*s[0] == '=' && !wspace)
-               *s += strspn(*s + 1, WHITESPACE) + 1;
-
-       return (old);
-}
-
-struct passwd *
-pwcopy(struct passwd *pw)
-{
-       struct passwd *copy = xmalloc(sizeof(*copy));
-
-       memset(copy, 0, sizeof(*copy));
-       copy->pw_name = xstrdup(pw->pw_name);
-       copy->pw_passwd = xstrdup(pw->pw_passwd);
-       copy->pw_gecos = xstrdup(pw->pw_gecos);
-       copy->pw_uid = pw->pw_uid;
-       copy->pw_gid = pw->pw_gid;
-#ifdef HAVE_PW_EXPIRE_IN_PASSWD
-       copy->pw_expire = pw->pw_expire;
-#endif
-#ifdef HAVE_PW_CHANGE_IN_PASSWD
-       copy->pw_change = pw->pw_change;
-#endif
-#ifdef HAVE_PW_CLASS_IN_PASSWD
-       copy->pw_class = xstrdup(pw->pw_class);
-#endif
-       copy->pw_dir = xstrdup(pw->pw_dir);
-       copy->pw_shell = xstrdup(pw->pw_shell);
-       return copy;
-}
-
-/*
- * Convert ASCII string to TCP/IP port number.
- * Port must be >0 and <=65535.
- * Return 0 if invalid.
- */
-int
-a2port(const char *s)
-{
-       long port;
-       char *endp;
-
-       errno = 0;
-       port = strtol(s, &endp, 0);
-       if (s == endp || *endp != '\0' ||
-           (errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) ||
-           port <= 0 || port > 65535)
-               return 0;
-
-       return port;
-}
-
-int
-a2tun(const char *s, int *remote)
-{
-       const char *errstr = NULL;
-       char *sp, *ep;
-       int tun;
-
-       if (remote != NULL) {
-               *remote = SSH_TUNID_ANY;
-               sp = xstrdup(s);
-               if ((ep = strchr(sp, ':')) == NULL) {
-                       xfree(sp);
-                       return (a2tun(s, NULL));
-               }
-               ep[0] = '\0'; ep++;
-               *remote = a2tun(ep, NULL);
-               tun = a2tun(sp, NULL);
-               xfree(sp);
-               return (*remote == SSH_TUNID_ERR ? *remote : tun);
-       }
-
-       if (strcasecmp(s, "any") == 0)
-               return (SSH_TUNID_ANY);
-
-       tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr);
-       if (errstr != NULL)
-               return (SSH_TUNID_ERR);
-
-       return (tun);
-}
-
-#define SECONDS                1
-#define MINUTES                (SECONDS * 60)
-#define HOURS          (MINUTES * 60)
-#define DAYS           (HOURS * 24)
-#define WEEKS          (DAYS * 7)
-
-/*
- * Convert a time string into seconds; format is
- * a sequence of:
- *      time[qualifier]
- *
- * Valid time qualifiers are:
- *      <none>  seconds
- *      s|S     seconds
- *      m|M     minutes
- *      h|H     hours
- *      d|D     days
- *      w|W     weeks
- *
- * Examples:
- *      90m     90 minutes
- *      1h30m   90 minutes
- *      2d      2 days
- *      1w      1 week
- *
- * Return -1 if time string is invalid.
- */
-long
-convtime(const char *s)
+xfree(void *ptr)
 {
-       long total, secs;
-       const char *p;
-       char *endp;
-
-       errno = 0;
-       total = 0;
-       p = s;
-
-       if (p == NULL || *p == '\0')
-               return -1;
-
-       while (*p) {
-               secs = strtol(p, &endp, 10);
-               if (p == endp ||
-                   (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) 
||
-                   secs < 0)
-                       return -1;
-
-               switch (*endp++) {
-               case '\0':
-                       endp--;
-               case 's':
-               case 'S':
-                       break;
-               case 'm':
-               case 'M':
-                       secs *= MINUTES;
-                       break;
-               case 'h':
-               case 'H':
-                       secs *= HOURS;
-                       break;
-               case 'd':
-               case 'D':
-                       secs *= DAYS;
-                       break;
-               case 'w':
-               case 'W':
-                       secs *= WEEKS;
-                       break;
-               default:
-                       return -1;
-               }
-               total += secs;
-               if (total < 0)
-                       return -1;
-               p = endp;
+       if (ptr == NULL) {
+               fprintf(stderr, "xfree: NULL pointer given as argument\n");
+               exit(EXIT_FAILURE);
        }
-
-       return total;
+       free(ptr);
 }
 
-/*
- * Search for next delimiter between hostnames/addresses and ports.
- * Argument may be modified (for termination).
- * Returns *cp if parsing succeeds.
- * *cp is set to the start of the next delimiter, if one was found.
- * If this is the last field, *cp is set to NULL.
- */
 char *
-hpdelim(char **cp)
+xstrdup(const char *str)
 {
-       char *s, *old;
-
-       if (cp == NULL || *cp == NULL)
-               return NULL;
-
-       old = s = *cp;
-       if (*s == '[') {
-               if ((s = strchr(s, ']')) == NULL)
-                       return NULL;
-               else
-                       s++;
-       } else if ((s = strpbrk(s, ":/")) == NULL)
-               s = *cp + strlen(*cp); /* skip to end (see first case below) */
-
-       switch (*s) {
-       case '\0':
-               *cp = NULL;     /* no more fields*/
-               break;
-
-       case ':':
-       case '/':
-               *s = '\0';      /* terminate */
-               *cp = s + 1;
-               break;
-
-       default:
-               return NULL;
-       }
+       size_t len;
+       char *cp;
 
-       return old;
+       len = strlen(str) + 1;
+       cp = xmalloc(len);
+       strncpy(cp, str, len);
+       return cp;
 }
 
 char *
@@ -449,205 +202,32 @@
 }
 
 /*
- * Expands tildes in the file name.  Returns data allocated by xmalloc.
- * Warning: this calls getpw*.
- */
-char *
-tilde_expand_filename(const char *filename, uid_t uid)
-{
-       const char *path;
-       char user[128], ret[MAXPATHLEN];
-       struct passwd *pw;
-       u_int len, slash;
-
-       if (*filename != '~')
-               return (xstrdup(filename));
-       filename++;
-
-       path = strchr(filename, '/');
-       if (path != NULL && path > filename) {          /* ~user/path */
-               slash = path - filename;
-               if (slash > sizeof(user) - 1)
-                       fatal("tilde_expand_filename: ~username too long");
-               memcpy(user, filename, slash);
-               user[slash] = '\0';
-               if ((pw = getpwnam(user)) == NULL)
-                       fatal("tilde_expand_filename: No such user %s", user);
-       } else if ((pw = getpwuid(uid)) == NULL)        /* ~/path */
-               fatal("tilde_expand_filename: No such uid %d", uid);
-
-       if (strlcpy(ret, pw->pw_dir, sizeof(ret)) >= sizeof(ret))
-               fatal("tilde_expand_filename: Path too long");
-
-       /* Make sure directory has a trailing '/' */
-       len = strlen(pw->pw_dir);
-       if ((len == 0 || pw->pw_dir[len - 1] != '/') &&
-           strlcat(ret, "/", sizeof(ret)) >= sizeof(ret))
-               fatal("tilde_expand_filename: Path too long");
-
-       /* Skip leading '/' from specified path */
-       if (path != NULL)
-               filename = path + 1;
-       if (strlcat(ret, filename, sizeof(ret)) >= sizeof(ret))
-               fatal("tilde_expand_filename: Path too long");
-
-       return (xstrdup(ret));
-}
-
-/*
- * Expand a string with a set of %[char] escapes. A number of escapes may be
- * specified as (char *escape_chars, char *replacement) pairs. The list must
- * be terminated by a NULL escape_char. Returns replaced string in memory
- * allocated by xmalloc.
+ * NB. duplicate __progname in case it is an alias for argv[0]
+ * Otherwise it may get clobbered by setproctitle()
  */
-char *
-percent_expand(const char *string, ...)
+char *ssh_get_progname(char *argv0)
 {
-#define EXPAND_MAX_KEYS        16
-       struct {
-               const char *key;
-               const char *repl;
-       } keys[EXPAND_MAX_KEYS];
-       u_int num_keys, i, j;
-       char buf[4096];
-       va_list ap;
-
-       /* Gather keys */
-       va_start(ap, string);
-       for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
-               keys[num_keys].key = va_arg(ap, char *);
-               if (keys[num_keys].key == NULL)
-                       break;
-               keys[num_keys].repl = va_arg(ap, char *);
-               if (keys[num_keys].repl == NULL)
-                       fatal("percent_expand: NULL replacement");
-       }
-       va_end(ap);
-
-       if (num_keys >= EXPAND_MAX_KEYS)
-               fatal("percent_expand: too many keys");
+       char *p;
 
-       /* Expand string */
-       *buf = '\0';
-       for (i = 0; *string != '\0'; string++) {
-               if (*string != '%') {
- append:
-                       buf[i++] = *string;
-                       if (i >= sizeof(buf))
-                               fatal("percent_expand: string too long");
-                       buf[i] = '\0';
-                       continue;
-               }
-               string++;
-               if (*string == '%')
-                       goto append;
-               for (j = 0; j < num_keys; j++) {
-                       if (strchr(keys[j].key, *string) != NULL) {
-                               i = strlcat(buf, keys[j].repl, sizeof(buf));
-                               if (i >= sizeof(buf))
-                                       fatal("percent_expand: string too 
long");
-                               break;
-                       }
-               }
-               if (j >= num_keys)
-                       fatal("percent_expand: unknown key %%%c", *string);
-       }
-       return (xstrdup(buf));
-#undef EXPAND_MAX_KEYS
-}
+       if (argv0 == NULL)
+               return ("unknown");     /* XXX */
+       p = strrchr(argv0, '/');
+       if (p == NULL)
+               p = argv0;
+       else
+               p++;
 
-/*
- * Read an entire line from a public key file into a static buffer, discarding
- * lines that exceed the buffer size.  Returns 0 on success, -1 on failure.
- */
-int
-read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
-   u_long *lineno)
-{
-       while (fgets(buf, bufsz, f) != NULL) {
-               (*lineno)++;
-               if (buf[strlen(buf) - 1] == '\n' || feof(f)) {
-                       return 0;
-               } else {
-                       debug("%s: %s line %lu exceeds size limit", __func__,
-                           filename, *lineno);
-                       /* discard remainder of line */
-                       while (fgetc(f) != '\n' && !feof(f))
-                               ;       /* nothing */
-               }
-       }
-       return -1;
+       return (xstrdup(p));
 }
 
-int
-tun_open(int tun, int mode)
+void fatal(char* fmt,...)
 {
-#if defined(CUSTOM_SYS_TUN_OPEN)
-       return (sys_tun_open(tun, mode));
-#elif defined(SSH_TUN_OPENBSD)
-       struct ifreq ifr;
-       char name[100];
-       int fd = -1, sock;
-
-       /* Open the tunnel device */
-       if (tun <= SSH_TUNID_MAX) {
-               snprintf(name, sizeof(name), "/dev/tun%d", tun);
-               fd = open(name, O_RDWR);
-       } else if (tun == SSH_TUNID_ANY) {
-               for (tun = 100; tun >= 0; tun--) {
-                       snprintf(name, sizeof(name), "/dev/tun%d", tun);
-                       if ((fd = open(name, O_RDWR)) >= 0)
-                               break;
-               }
-       } else {
-               debug("%s: invalid tunnel %u", __func__, tun);
-               return (-1);
-       }
-
-       if (fd < 0) {
-               debug("%s: %s open failed: %s", __func__, name, 
strerror(errno));
-               return (-1);
-       }
-
-       debug("%s: %s mode %d fd %d", __func__, name, mode, fd);
-
-       /* Set the tunnel device operation mode */
-       snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun);
-       if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
-               goto failed;
-
-       if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
-               goto failed;
-
-       /* Set interface mode */
-       ifr.ifr_flags &= ~IFF_UP;
-       if (mode == SSH_TUNMODE_ETHERNET)
-               ifr.ifr_flags |= IFF_LINK0;
-       else
-               ifr.ifr_flags &= ~IFF_LINK0;
-       if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
-               goto failed;
-
-       /* Bring interface up */
-       ifr.ifr_flags |= IFF_UP;
-       if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
-               goto failed;
-
-       close(sock);
-       return (fd);
-
- failed:
-       if (fd >= 0)
-               close(fd);
-       if (sock >= 0)
-               close(sock);
-       debug("%s: failed to set %s mode %d: %s", __func__, name,
-           mode, strerror(errno));
-       return (-1);
-#else
-       error("Tunnel interfaces are not supported on this platform");
-       return (-1);
-#endif
+       va_list args;
+       va_start(args, fmt);
+       vfprintf(stderr, fmt, args);
+       va_end(args);
+       fputc('\n', stderr);
+       exit(255);
 }
 
 void
@@ -671,20 +251,3 @@
        if (nullfd > 2)
                close(nullfd);
 }
-
-char *
-tohex(const u_char *d, u_int l)
-{
-       char b[3], *r;
-       u_int i, hl;
-
-       hl = l * 2 + 1;
-       r = xmalloc(hl);
-       *r = '\0';
-       for (i = 0; i < l; i++) {
-               snprintf(b, sizeof(b), "%02x", d[i]);
-               strlcat(r, b, hl);
-       }
-       return (r);
-}
-
diff -u a/progressmeter.c b/progressmeter.c
--- a/progressmeter.c
+++ b/progressmeter.c
@@ -1,3 +1,4 @@
+#ifdef PROGRESS_METER
 /*
  * Copyright (c) 2003 Nils Nordman.  All rights reserved.
  *
@@ -23,11 +24,11 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: progressmeter.c,v 1.24 2005/06/07 13:25:23 jaredy Exp $");
+/*RCSID("$OpenBSD: progressmeter.c,v 1.24 2005/06/07 13:25:23 jaredy Exp $");*/
 
 #include "progressmeter.h"
 #include "atomicio.h"
-#include "misc.h"
+#include "scpmisc.h"
 
 #define DEFAULT_WINSIZE 80
 #define MAX_WINSIZE 512
@@ -290,3 +291,4 @@
                win_size = DEFAULT_WINSIZE;
        win_size += 1;                                  /* trailing \0 */
 }
+#endif /* PROGRESS_METER */

Attachment: signature.asc
Description: PGP signature

Reply via email to