December 6, 2014.

The idea is to make a proper ssh implementation for Android.  Important
features:

   * it should run happily without root (on a non-root port)

   * it should be a regular android app requiring no special permissions,
     and not requiring any 'magic' executable files

   * should not rely on busybox

   * preferably support sftp

   * open source

The existing apps are either expensive, don't work, need root, or too
complicated, or a mix of all of the above.  And none of them are open
source.

I figure I'll start with dropbear, which I will run through JNI instead
of putting it in its own binary (because making such a binary executable
is a bit of a hack).

So that's the plan........


December 14, 2014.

I got dropbear to compile under the Android NDK, so now it's time to work
on the Android side of it.

I need:
  * a Service that can be started, stopped, and queried for whether it's
    running or not
  * a Thread to implement the Service's work (by calling into dropbear's
    main()), which can also be stopped.
  * a config UI with at least these choices:
    - bool: start on boot (def: false)
    - number: port number (def: 2222)
    - string: path to authorized_keys file (def: /sdcard/ssh)
    - string: name of default shell (def: /system/bin/sh -l)
    - string: default path for HOME (def: /sdcard/ssh)
    - button: start or (if it's running) stop


December 15, 2014.

Getting to the fun part.  Process management...

To start sshd, it seems like I can startService().  Then in the Service's
onStartCommand(), call startForeground() so it won't be killed (return
START_STICKY too?).

The question is if dropbear's main() should run under a separate Thread,
or a separate Process.  The trouble with a Thread is that it might be
hard to kill.  The trouble with a process is that there is no way to
report back status (such as a failure to start sshd).

Connectbot starts a new process for its shell -- it really doesn't have a
choice because the shell binary isn't linked with Connectbot, and exec()
in a thread stinks.  To stop it, it just closes stdin/stdout!!!  So
zombies can (and do) linger.

I suppose dropbear could be in its own process if it had something like
stdin/stdout to communicate failure?  Or it could just write error
messages to (i.e.) /sdcard/ssh/log.  To stop the service, it would just
use kill().

I am curious how the main waiting-for-connections loop looks, but even if
it uses select(), I'm not sure how I would honor Thread.interrupt() or
whatever.  It's not guaranteed to interrupt select(), and I'm not keen on
adding an arbitrary timeout/polling feature to it.


December 20, 2014.

So, I added a builtin scp endpoint.  It was pretty straight forward,
except dropbear defaults to vfork(), which blocks the parent until the
child runs execve()!!

Anyways, I noticed that scp doesn't quote its arguments to the remote
scp. That means you can't conveniently copy a remote file with a space in
its name (it becomes two files).  But the upside is that this is where
wildcards are handled -- by the shell!

So I need to either run it as a separate executable launched through the
shell, or make my own implementation of wildcards.

It is easy, using a $(BUILD_EXECUTABLE) script, to get ndk to build an
executable.  But it is only packaged up if it is named "gdbserver" (and
debug apk), or "libfoo.so".  The good news is that libfoo.so can be
executed in /data/data/org.galexander.sshd/lib/libfoo.so, so that is a
viable option.

Doing the expansion myself is not necessarily hard either, though.  I
need a library function called glob(), which is apparently not part of
bionic.  But I have the idea some cut and paste would resolve that with
very little extra work on my part.


December 21, 2014.

Well, bionic libc *does* provide fnmatch(), and even scandir() (a
shortcut for readdir).  In the best case, though, that still leaves me
with a bit of a path parsing conundrum (I have to tell scandir which
directory to operate on).  And also a bit of an escape character
conundrum -- \* and "*" should not act like wildcards.

Those are not insurmountable but I think I've talked myself out of it.
So then the question is, do I figure out how to ship an executable, or
do I do some hack like open a pipe to "/system/bin/sh echo filespec" and
use the shell solely for expansion?

I'm developing the idea that it's actually pretty easy to ship an
executable, I just need to find some -pre-package step where I can do
"mv scp libscp.so" and then it will ship.  ndk-build will not let me make
a target with a "." in it directly.


XXX - sftp (?)
XXX - rsync

XXX - document (ga.org/software/simplesshd/)
XXX - upload
