run minadbd as shell user, remove unused code

Make minadbd drop its root privileges after initializing.  We need to
make the /tmp directory writable by the shell group so that it can
drop the sideloaded file there.
diff --git a/minadbd/adb.c b/minadbd/adb.c
index d1e97b3..0e8fd2a 100644
--- a/minadbd/adb.c
+++ b/minadbd/adb.c
@@ -28,13 +28,9 @@
 #include "sysdeps.h"
 #include "adb.h"
 
-#if !ADB_HOST
 #include <private/android_filesystem_config.h>
 #include <linux/capability.h>
 #include <linux/prctl.h>
-#else
-#include "usb_vendors.h"
-#endif
 
 #if ADB_TRACE
 ADB_MUTEX_DEFINE( D_lock );
@@ -228,29 +224,6 @@
             HOST ? "host" : adb_device_banner);
     cp->msg.data_length = strlen((char*) cp->data) + 1;
     send_packet(cp, t);
-#if ADB_HOST
-        /* XXX why sleep here? */
-    // allow the device some time to respond to the connect message
-    adb_sleep_ms(1000);
-#endif
-}
-
-static char *connection_state_name(atransport *t)
-{
-    if (t == NULL) {
-        return "unknown";
-    }
-
-    switch(t->connection_state) {
-    case CS_BOOTLOADER:
-        return "bootloader";
-    case CS_DEVICE:
-        return "device";
-    case CS_OFFLINE:
-        return "offline";
-    default:
-        return "unknown";
-    }
 }
 
 void parse_banner(char *banner, atransport *t)
@@ -400,448 +373,11 @@
     put_apacket(p);
 }
 
-alistener listener_list = {
-    .next = &listener_list,
-    .prev = &listener_list,
-};
-
-static void ss_listener_event_func(int _fd, unsigned ev, void *_l)
-{
-    asocket *s;
-
-    if(ev & FDE_READ) {
-        struct sockaddr addr;
-        socklen_t alen;
-        int fd;
-
-        alen = sizeof(addr);
-        fd = adb_socket_accept(_fd, &addr, &alen);
-        if(fd < 0) return;
-
-        adb_socket_setbufsize(fd, CHUNK_SIZE);
-
-        s = create_local_socket(fd);
-        if(s) {
-            connect_to_smartsocket(s);
-            return;
-        }
-
-        adb_close(fd);
-    }
-}
-
-static void listener_event_func(int _fd, unsigned ev, void *_l)
-{
-    alistener *l = _l;
-    asocket *s;
-
-    if(ev & FDE_READ) {
-        struct sockaddr addr;
-        socklen_t alen;
-        int fd;
-
-        alen = sizeof(addr);
-        fd = adb_socket_accept(_fd, &addr, &alen);
-        if(fd < 0) return;
-
-        s = create_local_socket(fd);
-        if(s) {
-            s->transport = l->transport;
-            connect_to_remote(s, l->connect_to);
-            return;
-        }
-
-        adb_close(fd);
-    }
-}
-
-static void  free_listener(alistener*  l)
-{
-    if (l->next) {
-        l->next->prev = l->prev;
-        l->prev->next = l->next;
-        l->next = l->prev = l;
-    }
-
-    // closes the corresponding fd
-    fdevent_remove(&l->fde);
-
-    if (l->local_name)
-        free((char*)l->local_name);
-
-    if (l->connect_to)
-        free((char*)l->connect_to);
-
-    if (l->transport) {
-        remove_transport_disconnect(l->transport, &l->disconnect);
-    }
-    free(l);
-}
-
-static void listener_disconnect(void*  _l, atransport*  t)
-{
-    alistener*  l = _l;
-
-    free_listener(l);
-}
-
-int local_name_to_fd(const char *name)
-{
-    int port;
-
-    if(!strncmp("tcp:", name, 4)){
-        int  ret;
-        port = atoi(name + 4);
-        ret = socket_loopback_server(port, SOCK_STREAM);
-        return ret;
-    }
-#ifndef HAVE_WIN32_IPC  /* no Unix-domain sockets on Win32 */
-    // It's non-sensical to support the "reserved" space on the adb host side
-    if(!strncmp(name, "local:", 6)) {
-        return socket_local_server(name + 6,
-                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
-    } else if(!strncmp(name, "localabstract:", 14)) {
-        return socket_local_server(name + 14,
-                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
-    } else if(!strncmp(name, "localfilesystem:", 16)) {
-        return socket_local_server(name + 16,
-                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
-    }
-
-#endif
-    printf("unknown local portname '%s'\n", name);
-    return -1;
-}
-
-static int remove_listener(const char *local_name, const char *connect_to, atransport* transport)
-{
-    alistener *l;
-
-    for (l = listener_list.next; l != &listener_list; l = l->next) {
-        if (!strcmp(local_name, l->local_name) &&
-            !strcmp(connect_to, l->connect_to) &&
-            l->transport && l->transport == transport) {
-
-            listener_disconnect(l, transport);
-            return 0;
-        }
-    }
-
-    return -1;
-}
-
-static int install_listener(const char *local_name, const char *connect_to, atransport* transport)
-{
-    alistener *l;
-
-    //printf("install_listener('%s','%s')\n", local_name, connect_to);
-
-    for(l = listener_list.next; l != &listener_list; l = l->next){
-        if(strcmp(local_name, l->local_name) == 0) {
-            char *cto;
-
-                /* can't repurpose a smartsocket */
-            if(l->connect_to[0] == '*') {
-                return -1;
-            }
-
-            cto = strdup(connect_to);
-            if(cto == 0) {
-                return -1;
-            }
-
-            //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
-            free((void*) l->connect_to);
-            l->connect_to = cto;
-            if (l->transport != transport) {
-                remove_transport_disconnect(l->transport, &l->disconnect);
-                l->transport = transport;
-                add_transport_disconnect(l->transport, &l->disconnect);
-            }
-            return 0;
-        }
-    }
-
-    if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;
-    if((l->local_name = strdup(local_name)) == 0) goto nomem;
-    if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
-
-
-    l->fd = local_name_to_fd(local_name);
-    if(l->fd < 0) {
-        free((void*) l->local_name);
-        free((void*) l->connect_to);
-        free(l);
-        printf("cannot bind '%s'\n", local_name);
-        return -2;
-    }
-
-    close_on_exec(l->fd);
-    if(!strcmp(l->connect_to, "*smartsocket*")) {
-        fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
-    } else {
-        fdevent_install(&l->fde, l->fd, listener_event_func, l);
-    }
-    fdevent_set(&l->fde, FDE_READ);
-
-    l->next = &listener_list;
-    l->prev = listener_list.prev;
-    l->next->prev = l;
-    l->prev->next = l;
-    l->transport = transport;
-
-    if (transport) {
-        l->disconnect.opaque = l;
-        l->disconnect.func   = listener_disconnect;
-        add_transport_disconnect(transport, &l->disconnect);
-    }
-    return 0;
-
-nomem:
-    fatal("cannot allocate listener");
-    return 0;
-}
-
-#ifdef HAVE_WIN32_PROC
-static BOOL WINAPI ctrlc_handler(DWORD type)
-{
-    exit(STATUS_CONTROL_C_EXIT);
-    return TRUE;
-}
-#endif
-
 static void adb_cleanup(void)
 {
     usb_cleanup();
 }
 
-void start_logging(void)
-{
-#ifdef HAVE_WIN32_PROC
-    char    temp[ MAX_PATH ];
-    FILE*   fnul;
-    FILE*   flog;
-
-    GetTempPath( sizeof(temp) - 8, temp );
-    strcat( temp, "adb.log" );
-
-    /* Win32 specific redirections */
-    fnul = fopen( "NUL", "rt" );
-    if (fnul != NULL)
-        stdin[0] = fnul[0];
-
-    flog = fopen( temp, "at" );
-    if (flog == NULL)
-        flog = fnul;
-
-    setvbuf( flog, NULL, _IONBF, 0 );
-
-    stdout[0] = flog[0];
-    stderr[0] = flog[0];
-    fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
-#else
-    int fd;
-
-    fd = unix_open("/dev/null", O_RDONLY);
-    dup2(fd, 0);
-    adb_close(fd);
-
-    fd = unix_open("/tmp/adb.log", O_WRONLY | O_CREAT | O_APPEND, 0640);
-    if(fd < 0) {
-        fd = unix_open("/dev/null", O_WRONLY);
-    }
-    dup2(fd, 1);
-    dup2(fd, 2);
-    adb_close(fd);
-    fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
-#endif
-}
-
-#if !ADB_HOST
-void start_device_log(void)
-{
-    int fd;
-    char    path[PATH_MAX];
-    struct tm now;
-    time_t t;
-    char value[PROPERTY_VALUE_MAX];
-
-    // read the trace mask from persistent property persist.adb.trace_mask
-    // give up if the property is not set or cannot be parsed
-    property_get("persist.adb.trace_mask", value, "");
-    if (sscanf(value, "%x", &adb_trace_mask) != 1)
-        return;
-
-    adb_mkdir("/data/adb", 0775);
-    tzset();
-    time(&t);
-    localtime_r(&t, &now);
-    strftime(path, sizeof(path),
-                "/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt",
-                &now);
-    fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
-    if (fd < 0)
-        return;
-
-    // redirect stdout and stderr to the log file
-    dup2(fd, 1);
-    dup2(fd, 2);
-    fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
-    adb_close(fd);
-
-    fd = unix_open("/dev/null", O_RDONLY);
-    dup2(fd, 0);
-    adb_close(fd);
-}
-#endif
-
-#if ADB_HOST
-int launch_server(int server_port)
-{
-#ifdef HAVE_WIN32_PROC
-    /* we need to start the server in the background                    */
-    /* we create a PIPE that will be used to wait for the server's "OK" */
-    /* message since the pipe handles must be inheritable, we use a     */
-    /* security attribute                                               */
-    HANDLE                pipe_read, pipe_write;
-    SECURITY_ATTRIBUTES   sa;
-    STARTUPINFO           startup;
-    PROCESS_INFORMATION   pinfo;
-    char                  program_path[ MAX_PATH ];
-    int                   ret;
-
-    sa.nLength = sizeof(sa);
-    sa.lpSecurityDescriptor = NULL;
-    sa.bInheritHandle = TRUE;
-
-    /* create pipe, and ensure its read handle isn't inheritable */
-    ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
-    if (!ret) {
-        fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );
-        return -1;
-    }
-
-    SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );
-
-    ZeroMemory( &startup, sizeof(startup) );
-    startup.cb = sizeof(startup);
-    startup.hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
-    startup.hStdOutput = pipe_write;
-    startup.hStdError  = GetStdHandle( STD_ERROR_HANDLE );
-    startup.dwFlags    = STARTF_USESTDHANDLES;
-
-    ZeroMemory( &pinfo, sizeof(pinfo) );
-
-    /* get path of current program */
-    GetModuleFileName( NULL, program_path, sizeof(program_path) );
-
-    ret = CreateProcess(
-            program_path,                              /* program path  */
-            "adb fork-server server",
-                                    /* the fork-server argument will set the
-                                       debug = 2 in the child           */
-            NULL,                   /* process handle is not inheritable */
-            NULL,                    /* thread handle is not inheritable */
-            TRUE,                          /* yes, inherit some handles */
-            DETACHED_PROCESS, /* the new process doesn't have a console */
-            NULL,                     /* use parent's environment block */
-            NULL,                    /* use parent's starting directory */
-            &startup,                 /* startup info, i.e. std handles */
-            &pinfo );
-
-    CloseHandle( pipe_write );
-
-    if (!ret) {
-        fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );
-        CloseHandle( pipe_read );
-        return -1;
-    }
-
-    CloseHandle( pinfo.hProcess );
-    CloseHandle( pinfo.hThread );
-
-    /* wait for the "OK\n" message */
-    {
-        char  temp[3];
-        DWORD  count;
-
-        ret = ReadFile( pipe_read, temp, 3, &count, NULL );
-        CloseHandle( pipe_read );
-        if ( !ret ) {
-            fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );
-            return -1;
-        }
-        if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
-            fprintf(stderr, "ADB server didn't ACK\n" );
-            return -1;
-        }
-    }
-#elif defined(HAVE_FORKEXEC)
-    char    path[PATH_MAX];
-    int     fd[2];
-
-    // set up a pipe so the child can tell us when it is ready.
-    // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child.
-    if (pipe(fd)) {
-        fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
-        return -1;
-    }
-    get_my_path(path, PATH_MAX);
-    pid_t pid = fork();
-    if(pid < 0) return -1;
-
-    if (pid == 0) {
-        // child side of the fork
-
-        // redirect stderr to the pipe
-        // we use stderr instead of stdout due to stdout's buffering behavior.
-        adb_close(fd[0]);
-        dup2(fd[1], STDERR_FILENO);
-        adb_close(fd[1]);
-
-        // child process
-        int result = execl(path, "adb", "fork-server", "server", NULL);
-        // this should not return
-        fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
-    } else  {
-        // parent side of the fork
-
-        char  temp[3];
-
-        temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';
-        // wait for the "OK\n" message
-        adb_close(fd[1]);
-        int ret = adb_read(fd[0], temp, 3);
-        int saved_errno = errno;
-        adb_close(fd[0]);
-        if (ret < 0) {
-            fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);
-            return -1;
-        }
-        if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
-            fprintf(stderr, "ADB server didn't ACK\n" );
-            return -1;
-        }
-
-        setsid();
-    }
-#else
-#error "cannot implement background server start on this platform"
-#endif
-    return 0;
-}
-#endif
-
-/* Constructs a local name of form tcp:port.
- * target_str points to the target string, it's content will be overwritten.
- * target_size is the capacity of the target string.
- * server_port is the port number to use for the local name.
- */
-void build_local_name(char* target_str, size_t target_size, int server_port)
-{
-  snprintf(target_str, target_size, "tcp:%d", server_port);
-}
-
 int adb_main()
 {
     atexit(adb_cleanup);
@@ -858,6 +394,16 @@
         usb_init();
     }
 
+    if (setgid(AID_SHELL) != 0) {
+        fprintf(stderr, "failed to setgid to shell\n");
+        exit(1);
+    }
+    if (setuid(AID_SHELL) != 0) {
+        fprintf(stderr, "failed to setuid to shell\n");
+        exit(1);
+    }
+    fprintf(stderr, "userid is %d\n", getuid());
+
     D("Event loop starting\n");
 
     fdevent_loop();
@@ -866,286 +412,3 @@
 
     return 0;
 }
-
-#if ADB_HOST
-void connect_device(char* host, char* buffer, int buffer_size)
-{
-    int port, fd;
-    char* portstr = strchr(host, ':');
-    char hostbuf[100];
-    char serial[100];
-
-    strncpy(hostbuf, host, sizeof(hostbuf) - 1);
-    if (portstr) {
-        if (portstr - host >= sizeof(hostbuf)) {
-            snprintf(buffer, buffer_size, "bad host name %s", host);
-            return;
-        }
-        // zero terminate the host at the point we found the colon
-        hostbuf[portstr - host] = 0;
-        if (sscanf(portstr + 1, "%d", &port) == 0) {
-            snprintf(buffer, buffer_size, "bad port number %s", portstr);
-            return;
-        }
-    } else {
-        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
-    }
-
-    snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
-    if (find_transport(serial)) {
-        snprintf(buffer, buffer_size, "already connected to %s", serial);
-        return;
-    }
-
-    fd = socket_network_client(hostbuf, port, SOCK_STREAM);
-    if (fd < 0) {
-        snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
-        return;
-    }
-
-    D("client: connected on remote on fd %d\n", fd);
-    close_on_exec(fd);
-    disable_tcp_nagle(fd);
-    register_socket_transport(fd, serial, port, 0);
-    snprintf(buffer, buffer_size, "connected to %s", serial);
-}
-
-void connect_emulator(char* port_spec, char* buffer, int buffer_size)
-{
-    char* port_separator = strchr(port_spec, ',');
-    if (!port_separator) {
-        snprintf(buffer, buffer_size,
-                "unable to parse '%s' as <console port>,<adb port>",
-                port_spec);
-        return;
-    }
-
-    // Zero-terminate console port and make port_separator point to 2nd port.
-    *port_separator++ = 0;
-    int console_port = strtol(port_spec, NULL, 0);
-    int adb_port = strtol(port_separator, NULL, 0);
-    if (!(console_port > 0 && adb_port > 0)) {
-        *(port_separator - 1) = ',';
-        snprintf(buffer, buffer_size,
-                "Invalid port numbers: Expected positive numbers, got '%s'",
-                port_spec);
-        return;
-    }
-
-    /* Check if the emulator is already known.
-     * Note: There's a small but harmless race condition here: An emulator not
-     * present just yet could be registered by another invocation right
-     * after doing this check here. However, local_connect protects
-     * against double-registration too. From here, a better error message
-     * can be produced. In the case of the race condition, the very specific
-     * error message won't be shown, but the data doesn't get corrupted. */
-    atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
-    if (known_emulator != NULL) {
-        snprintf(buffer, buffer_size,
-                "Emulator on port %d already registered.", adb_port);
-        return;
-    }
-
-    /* Check if more emulators can be registered. Similar unproblematic
-     * race condition as above. */
-    int candidate_slot = get_available_local_transport_index();
-    if (candidate_slot < 0) {
-        snprintf(buffer, buffer_size, "Cannot accept more emulators.");
-        return;
-    }
-
-    /* Preconditions met, try to connect to the emulator. */
-    if (!local_connect_arbitrary_ports(console_port, adb_port)) {
-        snprintf(buffer, buffer_size,
-                "Connected to emulator on ports %d,%d", console_port, adb_port);
-    } else {
-        snprintf(buffer, buffer_size,
-                "Could not connect to emulator on ports %d,%d",
-                console_port, adb_port);
-    }
-}
-#endif
-
-int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
-{
-    atransport *transport = NULL;
-    char buf[4096];
-
-    if(!strcmp(service, "kill")) {
-        fprintf(stderr,"adb server killed by remote request\n");
-        fflush(stdout);
-        adb_write(reply_fd, "OKAY", 4);
-        usb_cleanup();
-        exit(0);
-    }
-
-#if ADB_HOST
-    // "transport:" is used for switching transport with a specified serial number
-    // "transport-usb:" is used for switching transport to the only USB transport
-    // "transport-local:" is used for switching transport to the only local transport
-    // "transport-any:" is used for switching transport to the only transport
-    if (!strncmp(service, "transport", strlen("transport"))) {
-        char* error_string = "unknown failure";
-        transport_type type = kTransportAny;
-
-        if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
-            type = kTransportUsb;
-        } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
-            type = kTransportLocal;
-        } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
-            type = kTransportAny;
-        } else if (!strncmp(service, "transport:", strlen("transport:"))) {
-            service += strlen("transport:");
-            serial = service;
-        }
-
-        transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
-
-        if (transport) {
-            s->transport = transport;
-            adb_write(reply_fd, "OKAY", 4);
-        } else {
-            sendfailmsg(reply_fd, error_string);
-        }
-        return 1;
-    }
-
-    // return a list of all connected devices
-    if (!strcmp(service, "devices")) {
-        char buffer[4096];
-        memset(buf, 0, sizeof(buf));
-        memset(buffer, 0, sizeof(buffer));
-        D("Getting device list \n");
-        list_transports(buffer, sizeof(buffer));
-        snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);
-        D("Wrote device list \n");
-        writex(reply_fd, buf, strlen(buf));
-        return 0;
-    }
-
-    // add a new TCP transport, device or emulator
-    if (!strncmp(service, "connect:", 8)) {
-        char buffer[4096];
-        char* host = service + 8;
-        if (!strncmp(host, "emu:", 4)) {
-            connect_emulator(host + 4, buffer, sizeof(buffer));
-        } else {
-            connect_device(host, buffer, sizeof(buffer));
-        }
-        // Send response for emulator and device
-        snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);
-        writex(reply_fd, buf, strlen(buf));
-        return 0;
-    }
-
-    // remove TCP transport
-    if (!strncmp(service, "disconnect:", 11)) {
-        char buffer[4096];
-        memset(buffer, 0, sizeof(buffer));
-        char* serial = service + 11;
-        if (serial[0] == 0) {
-            // disconnect from all TCP devices
-            unregister_all_tcp_transports();
-        } else {
-            char hostbuf[100];
-            // assume port 5555 if no port is specified
-            if (!strchr(serial, ':')) {
-                snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);
-                serial = hostbuf;
-            }
-            atransport *t = find_transport(serial);
-
-            if (t) {
-                unregister_transport(t);
-            } else {
-                snprintf(buffer, sizeof(buffer), "No such device %s", serial);
-            }
-        }
-
-        snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);
-        writex(reply_fd, buf, strlen(buf));
-        return 0;
-    }
-
-    // returns our value for ADB_SERVER_VERSION
-    if (!strcmp(service, "version")) {
-        char version[12];
-        snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
-        snprintf(buf, sizeof buf, "OKAY%04x%s", (unsigned)strlen(version), version);
-        writex(reply_fd, buf, strlen(buf));
-        return 0;
-    }
-
-    if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
-        char *out = "unknown";
-         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
-       if (transport && transport->serial) {
-            out = transport->serial;
-        }
-        snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(out),out);
-        writex(reply_fd, buf, strlen(buf));
-        return 0;
-    }
-    // indicates a new emulator instance has started
-    if (!strncmp(service,"emulator:",9)) {
-        int  port = atoi(service+9);
-        local_connect(port);
-        /* we don't even need to send a reply */
-        return 0;
-    }
-#endif // ADB_HOST
-
-    if(!strncmp(service,"forward:",8) || !strncmp(service,"killforward:",12)) {
-        char *local, *remote, *err;
-        int r;
-        atransport *transport;
-
-        int createForward = strncmp(service,"kill",4);
-
-        local = service + (createForward ? 8 : 12);
-        remote = strchr(local,';');
-        if(remote == 0) {
-            sendfailmsg(reply_fd, "malformed forward spec");
-            return 0;
-        }
-
-        *remote++ = 0;
-        if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){
-            sendfailmsg(reply_fd, "malformed forward spec");
-            return 0;
-        }
-
-        transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
-        if (!transport) {
-            sendfailmsg(reply_fd, err);
-            return 0;
-        }
-
-        if (createForward) {
-            r = install_listener(local, remote, transport);
-        } else {
-            r = remove_listener(local, remote, transport);
-        }
-        if(r == 0) {
-                /* 1st OKAY is connect, 2nd OKAY is status */
-            writex(reply_fd, "OKAYOKAY", 8);
-            return 0;
-        }
-
-        if (createForward) {
-            sendfailmsg(reply_fd, (r == -1) ? "cannot rebind smartsocket" : "cannot bind socket");
-        } else {
-            sendfailmsg(reply_fd, "cannot remove listener");
-        }
-        return 0;
-    }
-
-    if(!strncmp(service,"get-state",strlen("get-state"))) {
-        transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
-        char *state = connection_state_name(transport);
-        snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(state),state);
-        writex(reply_fd, buf, strlen(buf));
-        return 0;
-    }
-    return -1;
-}