Beispiel #1
0
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);
}
Beispiel #2
0
void start_device_log(void)
{
	int fd;
	char    path[PATH_MAX];
	struct tm now;
	time_t t;
	adb_mkdir("/var/adb", 0775);

	tzset();
	time(&t);
	localtime_r(&t, &now);
	strftime(path, sizeof(path),
			"/var/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);
}
Beispiel #3
0
static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
{
    D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
#ifdef HAVE_WIN32_PROC
    fprintf(stderr, "error: create_subproc_pty not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
    return -1;
#else /* !HAVE_WIN32_PROC */
    char *devname;
    int ptm;

    ptm = unix_open("/dev/ptmx", O_RDWR | O_CLOEXEC); // | O_NOCTTY);
    if(ptm < 0){
        printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
        return -1;
    }

    if(grantpt(ptm) || unlockpt(ptm) ||
       ((devname = (char*) ptsname(ptm)) == 0)){
        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    *pid = fork();
    if(*pid < 0) {
        printf("- fork failed: %s -\n", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    if (*pid == 0) {
        init_subproc_child();

        int pts = unix_open(devname, O_RDWR | O_CLOEXEC);
        if (pts < 0) {
            fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
            exit(-1);
        }

        dup2(pts, STDIN_FILENO);
        dup2(pts, STDOUT_FILENO);
        dup2(pts, STDERR_FILENO);

        adb_close(pts);
        adb_close(ptm);

        execl(cmd, cmd, arg0, arg1, NULL);
        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
                cmd, strerror(errno), errno);
        exit(-1);
    } else {
        return ptm;
    }
#endif /* !HAVE_WIN32_PROC */
}
void usb_init()
{
    usb_handle *h;
    adb_thread_t tid;
    int fd;

    h = calloc(1, sizeof(usb_handle));
    h->fd = -1;
    adb_cond_init(&h->notify, 0);
    adb_mutex_init(&h->lock, 0);

    // Open the file /dev/android_adb_enable to trigger 
    // the enabling of the adb USB function in the kernel.
    // We never touch this file again - just leave it open
    // indefinitely so the kernel will know when we are running
    // and when we are not.
    fd = unix_open("/dev/android_adb_enable", O_RDWR);
    if (fd < 0) {
       D("failed to open /dev/android_adb_enable\n");
    } else {
        close_on_exec(fd);
    }

    D("[ usb_init - starting thread ]\n");
    if(adb_thread_create(&tid, usb_open_thread, h)){
        fatal_errno("cannot create usb thread");
    }
}
/* we keep a list of opened transports. The atransport struct knows to which
 * local transport it is connected. The list is used to detect when we're
 * trying to connect twice to a given local transport.
 */
#define  SDB_LOCAL_TRANSPORT_MAX  16

SDB_MUTEX_DEFINE( local_transports_lock );

static atransport*  local_transports[ SDB_LOCAL_TRANSPORT_MAX ];
#endif /* SDB_HOST */

static int remote_read(apacket *p, atransport *t)
{
    if(readx(t->sfd, &p->msg, sizeof(amessage))){
        D("remote local: read terminated (message)\n");
        return -1;
    }

    fix_endians(p);

#if 0 && defined __ppc__
    D("read remote packet: %04x arg0=%0x arg1=%0x data_length=%0x data_check=%0x magic=%0x\n",
      p->msg.command, p->msg.arg0, p->msg.arg1, p->msg.data_length, p->msg.data_check, p->msg.magic);
#endif
    if(check_header(p)) {
        D("bad header: terminated (data)\n");
        return -1;
    }

    if(readx(t->sfd, p->data, p->msg.data_length)){
        D("remote local: terminated (data)\n");
        return -1;
    }

    if(check_data(p)) {
        D("bad data: terminated (data)\n");
        return -1;
    }

    return 0;
}

static int remote_write(apacket *p, atransport *t)
{
    int   length = p->msg.data_length;

    fix_endians(p);

#if 0 && defined __ppc__
    D("write remote packet: %04x arg0=%0x arg1=%0x data_length=%0x data_check=%0x magic=%0x\n",
      p->msg.command, p->msg.arg0, p->msg.arg1, p->msg.data_length, p->msg.data_check, p->msg.magic);
#endif
    if(writex(t->sfd, &p->msg, sizeof(amessage) + length)) {
        D("remote local: write terminated\n");
        return -1;
    }

    return 0;
}


int local_connect(int port, const char *device_name) {
    return local_connect_arbitrary_ports(port-1, port, device_name);
}

int local_connect_arbitrary_ports(int console_port, int sdb_port, const char *device_name)
{
    char buf[64];
    int  fd = -1;

#if SDB_HOST
    const char *host = getenv("SDBHOST");
    if (host) {
        fd = socket_network_client(host, sdb_port, SOCK_STREAM);
    }
#endif
    if (fd < 0) {
        fd = socket_loopback_client(sdb_port, SOCK_STREAM);
    }

    if (fd >= 0) {
        D("client: connected on remote on fd %d\n", fd);
        close_on_exec(fd);
        disable_tcp_nagle(fd);
        snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, console_port);
        register_socket_transport(fd, buf, sdb_port, 1, device_name);
        return 0;
    }
    return -1;
}

#if SDB_HOST /* tizen specific */
int get_devicename(int port, char *device_name)
{
    int fd;
    char buffer[MAX_PAYLOAD];
    char *tok = NULL;
    int found = 0;

    fd = unix_open(DEVICEMAP_FILENAME, O_RDONLY);
    if (fd > 0) {
        for(;;) {
            if(read_line(fd, buffer, MAX_PAYLOAD) < 0)
                break;
            tok = strtok(buffer, DEVICEMAP_SEPARATOR);
            if (tok != NULL) {
                strncpy(device_name, tok, DEVICENAME_MAX);
                tok = strtok(NULL, DEVICEMAP_SEPARATOR);
                if (tok != NULL) {
                    if (port == atoi(tok)) {
                        found = 1;
                        break;
                    }
                }
            }
        }
        sdb_close(fd);
    }
    if (found != 1)
        strncpy(device_name, DEFAULT_DEVICENAME, DEVICENAME_MAX);
    D("init device name %s on port %d\n", device_name, port);

    return found;
}
Beispiel #6
0
void start_logging(void)
{
	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());
}
Beispiel #7
0
/*** generic file functions */
void * file_open(char * filename, int mode, int creatmode, int buffering)
{
#ifdef WIN32
  return win32_open(filename, mode, creatmode, buffering);
#else
  return unix_open(filename, mode, creatmode, buffering);
#endif
}
static int create_subproc_pty(const char* cmd, const char* arg0,
                              const char* arg1, pid_t* pid) {
    D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
    char pts_name[PATH_MAX];
    int ptm;
    *pid = forkpty(&ptm, pts_name, nullptr, nullptr);
    if (*pid == -1) {
        printf("- fork failed: %s -\n", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    if (*pid == 0) {
        init_subproc_child();

        int pts = unix_open(pts_name, O_RDWR | O_CLOEXEC);
        if (pts == -1) {
            fprintf(stderr, "child failed to open pseudo-term slave %s: %s\n",
                    pts_name, strerror(errno));
            adb_close(ptm);
            exit(-1);
        }

        // arg0 is "-c" in batch mode and "-" in interactive mode.
        if (strcmp(arg0, "-c") == 0) {
            termios tattr;
            if (tcgetattr(pts, &tattr) == -1) {
                fprintf(stderr, "tcgetattr failed: %s\n", strerror(errno));
                adb_close(pts);
                adb_close(ptm);
                exit(-1);
            }

            cfmakeraw(&tattr);
            if (tcsetattr(pts, TCSADRAIN, &tattr) == -1) {
                fprintf(stderr, "tcsetattr failed: %s\n", strerror(errno));
                adb_close(pts);
                adb_close(ptm);
                exit(-1);
            }
        }

        dup2(pts, STDIN_FILENO);
        dup2(pts, STDOUT_FILENO);
        dup2(pts, STDERR_FILENO);

        adb_close(pts);
        adb_close(ptm);

        execl(cmd, cmd, arg0, arg1, nullptr);
        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
                cmd, strerror(errno), errno);
        exit(-1);
    } else {
        return ptm;
    }
}
void close_stdin() {
    int fd = unix_open("/dev/null", O_RDONLY);
    if (fd == -1) {
        perror("failed to open /dev/null, stdin will remain open");
        return;
    }
    dup2(fd, 0);
    adb_close(fd);
}
Beispiel #10
0
void start_logging(void)
{
#ifdef HAVE_WIN32_PROC
    char    temp[ MAX_PATH ];
    WCHAR   temp_[ MAX_PATH ];
    FILE*   fnul;
    FILE*   flog;

    GetTempPath( sizeof(temp) - 8, temp_ );
    wcstombs(temp, temp_, MAX_PATH);
    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
}
bool make_block_device_writable(const std::string& dev) {
    int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC);
    if (fd == -1) {
        return false;
    }

    int OFF = 0;
    bool result = (ioctl(fd, BLKROSET, &OFF) != -1);
    unix_close(fd);
    return result;
}
void close_stdin() {
    int fd = unix_open(kNullFileName, O_RDONLY);
    if (fd == -1) {
        fatal_errno("failed to open %s", kNullFileName);
    }

    if (TEMP_FAILURE_RETRY(dup2(fd, STDIN_FILENO)) == -1) {
        fatal_errno("failed to redirect stdin to %s", kNullFileName);
    }
    unix_close(fd);
}
void start_device_log(void) {
    int fd = unix_open(get_log_file_name().c_str(),
                       O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
    if (fd == -1) {
        return;
    }

    // Redirect stdout and stderr to the log file.
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);
    fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
    adb_close(fd);
}
void start_device_log(void)
{
    int fd;
    char    path[100];

    snprintf(path, sizeof path, "/data/adb_%ld.txt", (long)time(NULL));
    fd = unix_open(path, O_WRONLY | O_CREAT | O_APPEND, 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());

    fd = unix_open("/dev/null", O_RDONLY);
    dup2(fd, 0);

    // log everything
    adb_trace_mask = ~0;
    // except TRACE_RWX is a bit too verbose
    adb_trace_mask &= ~TRACE_RWX;
}
static void *usb_open_thread(void *x)
{
    struct usb_handle *usb = (struct usb_handle *)x;
    int fd;

    while (1) {
        // wait until the USB device needs opening
        adb_mutex_lock(&usb->lock);
        while (usb->fd != -1)
            adb_cond_wait(&usb->notify, &usb->lock);
        adb_mutex_unlock(&usb->lock);

        D("[ usb_thread - opening device ]\n");
        do {
            /* XXX use inotify? */
            fd = unix_open("/dev/android_adb", O_RDWR);
            if (fd < 0) {
                // to support older kernels
                fd = unix_open("/dev/android", O_RDWR);
            }
            if (fd < 0) {
                adb_sleep_ms(1000);
            }
        } while (fd < 0);
        D("[ opening device succeeded ]\n");

        close_on_exec(fd);
        usb->fd = fd;

        D("[ usb_thread - registering device ]\n");
        register_usb_transport(usb, 0, 1);
    }

    // never gets here
    return 0;
}
static void setup_daemon_logging(void) {
    const std::string log_file_path(GetLogFilePath());
    int fd = unix_open(log_file_path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0640);
    if (fd == -1) {
        fatal("cannot open '%s': %s", log_file_path.c_str(), strerror(errno));
    }
    if (dup2(fd, STDOUT_FILENO) == -1) {
        fatal("cannot redirect stdout: %s", strerror(errno));
    }
    if (dup2(fd, STDERR_FILENO) == -1) {
        fatal("cannot redirect stderr: %s", strerror(errno));
    }
    unix_close(fd);

    fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
    LOG(INFO) << adb_version();
}
static void status_window(transport_type ttype, const char* serial)
{
    char command[4096];
    char *state = 0;
    char *laststate = 0;

        /* silence stderr */
#ifdef _WIN32
    /* XXX: TODO */
#else
    int  fd;
    fd = unix_open("/dev/null", O_WRONLY);
    dup2(fd, 2);
    adb_close(fd);
#endif

    format_host_command(command, sizeof command, "get-state", ttype, serial);

    for(;;) {
        adb_sleep_ms(250);

        if(state) {
            free(state);
            state = 0;
        }

        state = adb_query(command);

        if(state) {
            if(laststate && !strcmp(state,laststate)){
                continue;
            } else {
                if(laststate) free(laststate);
                laststate = strdup(state);
            }
        }

        printf("%c[2J%c[2H", 27, 27);
        printf("Android Debug Bridge\n");
        printf("State: %s\n", state ? state : "offline");
        fflush(stdout);
    }
}
void log_service(int fd, void *cookie)
{
    /* get the name of the log filepath to read */
    char * log_filepath = cookie;

    /* open the log file. */
    int logfd = unix_open(log_filepath, O_RDONLY);
    if (logfd < 0) {
        goto done;
    }

    // temp buffer to read the entries
    unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4)));
    struct logger_entry *entry = (struct logger_entry *) buf;

    while (1) {
        int ret;

        ret = unix_read(logfd, entry, LOGGER_ENTRY_MAX_LEN);
        if (ret < 0) {
            if (errno == EINTR || errno == EAGAIN)
                continue;
            // perror("logcat read");
            goto done;
        }
        else if (!ret) {
            // fprintf(stderr, "read: Unexpected EOF!\n");
            goto done;
        }

        /* NOTE: driver guarantees we read exactly one full entry */

        entry->msg[entry->len] = '\0';

        write_log_entry(fd, entry);
    }

done:
    unix_close(fd);
    free(log_filepath);
}
Beispiel #19
0
void start_device_log(void) {
    struct tm now;
    time_t t;
    tzset();
    time(&t);
    localtime_r(&t, &now);

    char timestamp[PATH_MAX];
    strftime(timestamp, sizeof(timestamp), "%Y-%m-%d-%H-%M-%S", &now);

    std::string path = android::base::StringPrintf("/data/adb/adb-%s-%d", timestamp, getpid());
    int fd = unix_open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
    if (fd == -1) {
        return;
    }

    // redirect stdout and stderr to the log file
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);
    fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
    adb_close(fd);
}
/* Returns the device used to mount a directory in /proc/mounts */
static char *find_mount(const char *dir)
{
    int fd;
    int res;
    int size;
    char *token = NULL;
    const char delims[] = "\n";
    char buf[4096];

    fd = unix_open("/proc/mounts", O_RDONLY);
    if (fd < 0)
        return NULL;

    buf[sizeof(buf) - 1] = '\0';
    size = sdb_read(fd, buf, sizeof(buf) - 1);
    sdb_close(fd);

    token = strtok(buf, delims);

    while (token) {
        char mount_dev[256];
        char mount_dir[256];
        int mount_freq;
        int mount_passno;

        res = sscanf(token, "%255s %255s %*s %*s %d %d\n",
                     mount_dev, mount_dir, &mount_freq, &mount_passno);
        mount_dev[255] = 0;
        mount_dir[255] = 0;
        if (res == 4 && (strcmp(dir, mount_dir) == 0))
            return strdup(mount_dev);

        token = strtok(NULL, delims);
    }
    return NULL;
}
int service_to_fd(const char* name, const atransport* transport) {
    int ret = -1;

    if(!strncmp(name, "tcp:", 4)) {
        int port = atoi(name + 4);
        name = strchr(name + 4, ':');
        if(name == 0) {
            std::string error;
            ret = network_loopback_client(port, SOCK_STREAM, &error);
            if (ret >= 0)
                disable_tcp_nagle(ret);
        } else {
#if ADB_HOST
            std::string error;
            ret = network_connect(name + 1, port, SOCK_STREAM, 0, &error);
#else
            return -1;
#endif
        }
#if !defined(_WIN32)   /* winsock doesn't implement unix domain sockets */
    } else if(!strncmp(name, "local:", 6)) {
        ret = socket_local_client(name + 6,
                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    } else if(!strncmp(name, "localreserved:", 14)) {
        ret = socket_local_client(name + 14,
                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    } else if(!strncmp(name, "localabstract:", 14)) {
        ret = socket_local_client(name + 14,
                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
    } else if(!strncmp(name, "localfilesystem:", 16)) {
        ret = socket_local_client(name + 16,
                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
#endif
#if !ADB_HOST
    } else if(!strncmp("dev:", name, 4)) {
        ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);
    } else if(!strncmp(name, "framebuffer:", 12)) {
        ret = create_service_thread(framebuffer_service, 0);
    } else if (!strncmp(name, "jdwp:", 5)) {
        ret = create_jdwp_connection_fd(atoi(name+5));
    } else if(!strncmp(name, "shell", 5)) {
        ret = ShellService(name + 5, transport);
    } else if(!strncmp(name, "exec:", 5)) {
        ret = StartSubprocess(name + 5, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
    } else if(!strncmp(name, "sync:", 5)) {
        ret = create_service_thread(file_sync_service, NULL);
    } else if(!strncmp(name, "remount:", 8)) {
        ret = create_service_thread(remount_service, NULL);
    } else if(!strncmp(name, "reboot:", 7)) {
        void* arg = strdup(name + 7);
        if (arg == NULL) return -1;
        ret = create_service_thread(reboot_service, arg);
    } else if(!strncmp(name, "root:", 5)) {
        ret = create_service_thread(restart_root_service, NULL);
    } else if(!strncmp(name, "unroot:", 7)) {
        ret = create_service_thread(restart_unroot_service, NULL);
    } else if(!strncmp(name, "backup:", 7)) {
        ret = StartSubprocess(android::base::StringPrintf("/system/bin/bu backup %s",
                                                          (name + 7)).c_str(),
                              nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
    } else if(!strncmp(name, "restore:", 8)) {
        ret = StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,
                              SubprocessProtocol::kNone);
    } else if(!strncmp(name, "tcpip:", 6)) {
        int port;
        if (sscanf(name + 6, "%d", &port) != 1) {
            return -1;
        }
        ret = create_service_thread(restart_tcp_service, (void *) (uintptr_t) port);
    } else if(!strncmp(name, "usb:", 4)) {
        ret = create_service_thread(restart_usb_service, NULL);
    } else if (!strncmp(name, "reverse:", 8)) {
        ret = reverse_service(name + 8);
    } else if(!strncmp(name, "disable-verity:", 15)) {
        ret = create_service_thread(set_verity_enabled_state_service, (void*)0);
    } else if(!strncmp(name, "enable-verity:", 15)) {
        ret = create_service_thread(set_verity_enabled_state_service, (void*)1);
#endif
    }
    if (ret >= 0) {
        close_on_exec(ret);
    }
    return ret;
}
Beispiel #22
0
int service_to_fd(const char *name)
{
    int ret = -1;

    if(!strncmp(name, "tcp:", 4)) {
        int port = atoi(name + 4);
        name = strchr(name + 4, ':');
        if(name == 0) {
            ret = socket_loopback_client(port, SOCK_STREAM);
            if (ret >= 0)
                disable_tcp_nagle(ret);
        } else {
#if ADB_HOST
            ret = socket_network_client(name + 1, port, SOCK_STREAM);
#else
            return -1;
#endif
        }
#ifndef HAVE_WINSOCK   /* winsock doesn't implement unix domain sockets */
    } else if(!strncmp(name, "local:", 6)) {
        ret = socket_local_client(name + 6,
                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    } else if(!strncmp(name, "localreserved:", 14)) {
        ret = socket_local_client(name + 14,
                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    } else if(!strncmp(name, "localabstract:", 14)) {
        ret = socket_local_client(name + 14,
                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
    } else if(!strncmp(name, "localfilesystem:", 16)) {
        ret = socket_local_client(name + 16,
                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
#endif
#if !ADB_HOST
    } else if(!strncmp("dev:", name, 4)) {
        ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);
    } else if(!strncmp(name, "framebuffer:", 12)) {
        ret = create_service_thread(framebuffer_service, 0);
    } else if (!strncmp(name, "jdwp:", 5)) {
        ret = create_jdwp_connection_fd(atoi(name+5));
    } else if(!HOST && !strncmp(name, "shell:", 6)) {
        ret = create_subproc_thread(name + 6, SUBPROC_PTY);
    } else if(!HOST && !strncmp(name, "exec:", 5)) {
        ret = create_subproc_thread(name + 5, SUBPROC_RAW);
    } else if(!strncmp(name, "sync:", 5)) {
        ret = create_service_thread(file_sync_service, NULL);
    } else if(!strncmp(name, "remount:", 8)) {
        ret = create_service_thread(remount_service, NULL);
    } else if(!strncmp(name, "reboot:", 7)) {
        void* arg = strdup(name + 7);
        if (arg == NULL) return -1;
        ret = create_service_thread(reboot_service, arg);
    } else if(!strncmp(name, "root:", 5)) {
        ret = create_service_thread(restart_root_service, NULL);
    } else if(!strncmp(name, "backup:", 7)) {
        char* arg = strdup(name + 7);
        if (arg == NULL) return -1;
        char* c = arg;
        for (; *c != '\0'; c++) {
            if (*c == ':')
                *c = ' ';
        }
        char* cmd;
        if (asprintf(&cmd, "%s backup %s", bu_path(), arg) != -1) {
            ret = create_subproc_thread(cmd, SUBPROC_RAW);
            free(cmd);
        }
        free(arg);
    } else if(!strncmp(name, "restore:", 8)) {
        char* cmd;
        if (asprintf(&cmd, "%s restore", bu_path()) != -1) {
            ret = create_subproc_thread(cmd, SUBPROC_RAW);
            free(cmd);
        }
    } else if(!strncmp(name, "tcpip:", 6)) {
        int port;
        if (sscanf(name + 6, "%d", &port) == 0) {
            port = 0;
        }
        ret = create_service_thread(restart_tcp_service, (void *) (uintptr_t) port);
    } else if(!strncmp(name, "usb:", 4)) {
        ret = create_service_thread(restart_usb_service, NULL);
    } else if (!strncmp(name, "reverse:", 8)) {
        char* cookie = strdup(name + 8);
        if (cookie == NULL) {
            ret = -1;
        } else {
            ret = create_service_thread(reverse_service, cookie);
            if (ret < 0) {
                free(cookie);
            }
        }
#endif
    }
    if (ret >= 0) {
        close_on_exec(ret);
    }
    return ret;
}
Beispiel #23
0
int service_to_fd(const char* name, const atransport* transport) {
    int ret = -1;

    if (is_socket_spec(name)) {
        std::string error;
        ret = socket_spec_connect(name, &error);
        if (ret < 0) {
            LOG(ERROR) << "failed to connect to socket '" << name << "': " << error;
        }
#if !ADB_HOST
    } else if(!strncmp("dev:", name, 4)) {
        ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);
    } else if(!strncmp(name, "framebuffer:", 12)) {
        ret = create_service_thread(framebuffer_service, 0);
    } else if (!strncmp(name, "jdwp:", 5)) {
        ret = create_jdwp_connection_fd(atoi(name+5));
    } else if(!strncmp(name, "shell", 5)) {
        ret = ShellService(name + 5, transport);
    } else if(!strncmp(name, "exec:", 5)) {
        ret = StartSubprocess(name + 5, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
    } else if(!strncmp(name, "sync:", 5)) {
        ret = create_service_thread(file_sync_service, NULL);
    } else if(!strncmp(name, "remount:", 8)) {
        ret = create_service_thread(remount_service, NULL);
    } else if(!strncmp(name, "reboot:", 7)) {
        void* arg = strdup(name + 7);
        if (arg == NULL) return -1;
        ret = create_service_thread(reboot_service, arg);
    } else if(!strncmp(name, "root:", 5)) {
        ret = create_service_thread(restart_root_service, NULL);
    } else if(!strncmp(name, "unroot:", 7)) {
        ret = create_service_thread(restart_unroot_service, NULL);
    } else if(!strncmp(name, "backup:", 7)) {
        ret = StartSubprocess(android::base::StringPrintf("/system/bin/bu backup %s",
                                                          (name + 7)).c_str(),
                              nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
    } else if(!strncmp(name, "restore:", 8)) {
        ret = StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,
                              SubprocessProtocol::kNone);
    } else if(!strncmp(name, "tcpip:", 6)) {
        int port;
        if (sscanf(name + 6, "%d", &port) != 1) {
            return -1;
        }
        ret = create_service_thread(restart_tcp_service, (void *) (uintptr_t) port);
    } else if(!strncmp(name, "usb:", 4)) {
        ret = create_service_thread(restart_usb_service, NULL);
    } else if (!strncmp(name, "reverse:", 8)) {
        ret = reverse_service(name + 8);
    } else if(!strncmp(name, "disable-verity:", 15)) {
        ret = create_service_thread(set_verity_enabled_state_service, (void*)0);
    } else if(!strncmp(name, "enable-verity:", 15)) {
        ret = create_service_thread(set_verity_enabled_state_service, (void*)1);
    } else if (!strcmp(name, "reconnect")) {
        ret = create_service_thread(reconnect_service, const_cast<atransport*>(transport));
#endif
    }
    if (ret >= 0) {
        close_on_exec(ret);
    }
    return ret;
}
Beispiel #24
0
static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
{
#ifdef HAVE_WIN32_PROC
	fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
	return -1;
#else /* !HAVE_WIN32_PROC */
    char *devname;
    int ptm;
    pid_t pid;

    ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
    if(ptm < 0){
        printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
        return -1;
    }
    fcntl(ptm, F_SETFD, FD_CLOEXEC);

    if(grantpt(ptm) || unlockpt(ptm) ||
       ((devname = (char*) ptsname(ptm)) == 0)){
        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
        return -1;
    }

    pid = fork();
    if(pid < 0) {
        printf("- fork failed: %s -\n", strerror(errno));
        return -1;
    }

    if(pid == 0){
        int pts;

        setsid();

        pts = unix_open(devname, O_RDWR);
        if(pts < 0) exit(-1);

        dup2(pts, 0);
        dup2(pts, 1);
        dup2(pts, 2);

        adb_close(ptm);

        execl(cmd, cmd, arg0, arg1, NULL);
        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
                cmd, strerror(errno), errno);
        exit(-1);
    } else {
#if !ADB_HOST
        // set child's OOM adjustment to zero
        char text[64];
        snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
        int fd = adb_open(text, O_WRONLY);
        if (fd >= 0) {
            adb_write(fd, "0", 1);
            adb_close(fd);
        } else {
           D("adb: unable to open %s\n", text);
        }
#endif
        return ptm;
    }
#endif /* !HAVE_WIN32_PROC */
}
Beispiel #25
0
static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
{
    D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
#ifdef HAVE_WIN32_PROC
    fprintf(stderr, "error: create_subproc_pty not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
    return -1;
#else /* !HAVE_WIN32_PROC */
    int ptm;

    ptm = unix_open("/dev/ptmx", O_RDWR | O_CLOEXEC); // | O_NOCTTY);
    if(ptm < 0){
        printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
        return -1;
    }

    char devname[64];
    if(grantpt(ptm) || unlockpt(ptm) || ptsname_r(ptm, devname, sizeof(devname)) != 0) {
        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    *pid = fork();
    if(*pid < 0) {
        printf("- fork failed: %s -\n", strerror(errno));
        XLOGW("- fork failed: pid(%d) %s -\n", *pid, strerror(errno));
        adb_close(ptm);
        return -1;
    }

    if (*pid == 0) {
        init_subproc_child();

        int pts = unix_open(devname, O_RDWR | O_CLOEXEC);
        if (pts < 0) {
            fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
            exit(-1);
        }

        dup2(pts, STDIN_FILENO);
        dup2(pts, STDOUT_FILENO);
        dup2(pts, STDERR_FILENO);

        adb_close(pts);
        adb_close(ptm);

        timer_t timerid;
        struct sigevent sev;
        /* Create the timer */
        sev.sigev_notify = SIGEV_SIGNAL;
        sev.sigev_signo = SIGALRM;
        sev.sigev_value.sival_ptr = &timerid;
        if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1)
        {
            D("adb: Call timer_create failed!\n");
            XLOGV("adb: Call timer_create failed!\n");
            exit(-1);
        }

        struct itimerspec its;
        /* Start the timer */
        its.it_value.tv_sec = 1;
        its.it_value.tv_nsec = 0;
        its.it_interval.tv_sec = 3;
        its.it_interval.tv_nsec = 0;

        if (timer_settime(timerid, 0, &its, NULL) == -1)
        {
            D("adb: Call timer_settime failed!\n");
            XLOGV("adb: Call timer_settime failed!\n");
            exit(-1);
        }

        sigset_t mask;
        struct sigaction sa;
        /* Establish handler for timer signal */
        sa.sa_flags = SA_SIGINFO;
        sa.sa_sigaction = catcher;
        sigemptyset(&sa.sa_mask);
        if (sigaction(SIGALRM, &sa, NULL) == -1)
        {
            D("adb: Call sigaction failed!\n");
            XLOGV("adb: Call sigaction failed!\n");
            exit(-1);
        }

        int nRet = execl(cmd, cmd, arg0, arg1, NULL);
        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
                cmd, strerror(errno), errno);
        XLOGV("- exec '%s' failed: %s (%d) nRet(%d) -\n",
                cmd, strerror(errno), errno, nRet);
        exit(-1);
    } else {
        return ptm;
    }
#endif /* !HAVE_WIN32_PROC */
}
Beispiel #26
0
static int create_subprocess(const char *cmd, const char *arg0,
                             const char *arg1, pid_t * pid)
{
#ifdef HAVE_WIN32_PROC
    D("create_subprocess(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
    fprintf(stderr,
            "error: create_subprocess not implemented on Win32 (%s %s %s)\n",
            cmd, arg0, arg1);
    return -1;
#else                           /* !HAVE_WIN32_PROC */
    char *devname;
    int ptm;

    ptm = unix_open("/dev/ptmx", O_RDWR);   // | O_NOCTTY);
    if (ptm < 0) {
        printf("[ cannot open /dev/ptmx - %s ]\n", strerror(errno));
        return -1;
    }
    fcntl(ptm, F_SETFD, FD_CLOEXEC);

    if (grantpt(ptm) || unlockpt(ptm) ||
        ((devname = (char *) ptsname(ptm)) == 0)) {
        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    *pid = fork();
    if (*pid < 0) {
        printf("- fork failed: %s -\n", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    if (*pid == 0) {
        int pts;

        setsid();

        pts = unix_open(devname, O_RDWR);
        if (pts < 0) {
            fprintf(stderr, "child failed to open pseudo-term slave: %s\n",
                    devname);
            exit(-1);
        }

        dup2(pts, 0);
        dup2(pts, 1);
        dup2(pts, 2);

        adb_close(pts);
        adb_close(ptm);

        // set OOM adjustment to zero
        char text[64];
        snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid());
        int fd = adb_open(text, O_WRONLY);
        if (fd >= 0) {
            adb_write(fd, "0", 1);
            adb_close(fd);
        } else {
            D("adb: unable to open %s\n", text);
        }
        execl(cmd, cmd, arg0, arg1, NULL);
        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
                cmd, strerror(errno), errno);
        exit(-1);
    } else {
        // Don't set child's OOM adjustment to zero.
        // Let the child do it itself, as sometimes the parent starts
        // running before the child has a /proc/pid/oom_adj.
        // """adb: unable to open /proc/644/oom_adj""" seen in some logs.
        return ptm;
    }
#endif                          /* !HAVE_WIN32_PROC */
}
Beispiel #27
0
NTSTATUS NTAPI NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize,
    ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength)
{
#ifdef _WIN32
    HANDLE hFile;
    LARGE_INTEGER size;
#endif

    DECLAREVARCONV(ObjectAttributesA);
    CHECK_POINTER(FileHandle);
    CHECK_POINTER(IoStatusBlock);

    OA2STR(ObjectAttributes);

    IoStatusBlock->Information = FILE_DOES_NOT_EXIST;

#ifdef REDIR_IO
    {
        IO_STATUS_BLOCK iob;
        FILE_STANDARD_INFORMATION fi;

        NTSTATUS res = ftbl.nt.NtCreateFile(&hFile, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes,
            ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength);

        if (res < 0)
        {
            Log("ntdll.NtCreateFile(\"%s\", 0x%08x) = 0x%08x\n", ObjectAttributesA, DesiredAccess, res);
            return res;
        }

        __CreateHandle(*FileHandle, HANDLE_FILE, ObjectAttributesA);
        (*FileHandle)->file.mode = DesiredAccess;
        (*FileHandle)->file.fh = hFile;

        res = ftbl.nt.NtQueryInformationFile(hFile, &iob, &fi, sizeof(fi), FileStandardInformation);

        if (res == STATUS_SUCCESS)
            (*FileHandle)->file.st.st_size = fi.EndOfFile.QuadPart;
        else
        {
            GET_LENGTH_INFORMATION gli;
            if ((res = ftbl.nt.NtDeviceIoControlFile(hFile, NULL, NULL, NULL, IoStatusBlock, IOCTL_DISK_GET_LENGTH_INFO,
                    NULL, 0, &gli, sizeof(GET_LENGTH_INFORMATION))) < 0)
            {
                //fprintf(stderr, "NtOpenFile() - Unable to get size of %s: 0x%08x\n", ObjectAttributesA, res);
                // KeyboardClass etc
                (*FileHandle)->file.st.st_size = 0;
            }
            else
                (*FileHandle)->file.st.st_size = gli.Length.QuadPart;
        }
    }
#endif /* REDIR_IO */

    Log("ntdll.NtCreateFile(\"%s\", 0x%08x)\n", ObjectAttributesA, DesiredAccess);

#ifdef _WIN32
    hFile = CreateFileW(ObjectAttributes->ObjectName->Buffer, (DesiredAccess << 8) & 0xf0000000, ShareAccess, NULL, CreateDisposition, FileAttributes, NULL);

    if (hFile == INVALID_HANDLE_VALUE)
    {
        DWORD err = GetLastError();
        if (err != 3 /* ERROR_PATH_NOT_FOUND */)
            fwprintf(stderr, L"CreateFileW '%s' failed with %d\n", ObjectAttributes->ObjectName->Buffer, GetLastError());
        return (IoStatusBlock->u.Status = STATUS_OBJECT_NAME_NOT_FOUND);
    }

    if (!GetFileSizeEx(hFile, &size))
    {
        fprintf(stderr, "CreateFileW() - Unable to get size of %s: %d\n", ObjectAttributesA, GetLastError());
        return (IoStatusBlock->u.Status = STATUS_OBJECT_NAME_NOT_FOUND);
    }

    __CreateHandle(*FileHandle, HANDLE_FILE, ObjectAttributesA);
    (*FileHandle)->file.fh = hFile;
    (*FileHandle)->file.mode = DesiredAccess;
    (*FileHandle)->file.st.st_size = size.QuadPart;

#else /* _WIN32 */
    int fd = unix_open(ObjectAttributesA, ntflags_unix(DesiredAccess));
    struct stat st;

    if ((fd < 0) || (fstat(fd, &st) < 0))
        return (IoStatusBlock->u.Status = STATUS_OBJECT_NAME_NOT_FOUND);


#if defined(BLKGETSIZE64)
    if (S_ISBLK(st.st_mode) && (ioctl(fd, BLKGETSIZE64, &st.st_size) < 0))
#elif defined(DIOCGMEDIASIZE)
	if (S_ISCHR(st.st_mode) && (ioctl(fd, DIOCGMEDIASIZE, &st.st_size) < 0))
#else
    if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
#endif
        st.st_size = 0;

    __CreateHandle(*FileHandle, HANDLE_FILE, ObjectAttributesA);
    (*FileHandle)->file.fh = fd;
    (*FileHandle)->file.mode = DesiredAccess;
    memcpy(&(*FileHandle)->file.st, &st, sizeof(st));

#endif /* _WIN32 */

    IoStatusBlock->Information = FILE_CREATED;
    return (IoStatusBlock->u.Status = STATUS_SUCCESS);
}
Beispiel #28
0
static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
{
#ifdef HAVE_WIN32_PROC
    D("create_subprocess(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
    fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
    return -1;
#else /* !HAVE_WIN32_PROC */
    char *devname;
    int ptm;

    ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
    if(ptm < 0){
        printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
        return -1;
    }
    fcntl(ptm, F_SETFD, FD_CLOEXEC);

    if(grantpt(ptm) || unlockpt(ptm) ||
       ((devname = (char*) ptsname(ptm)) == 0)){
        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    *pid = fork();
    if(*pid < 0) {
        printf("- fork failed: pid(%d) %s -\n", *pid, strerror(errno));
        XLOGV("- fork failed: pid(%d) %s -\n", *pid, strerror(errno));
        adb_close(ptm);
        return -1;
    }

    if(*pid == 0){
        int pts;

        setsid();

        pts = unix_open(devname, O_RDWR);
        if(pts < 0) {
            fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
            XLOGV("child failed to open pseudo-term slave: %s\n", devname);
            exit(-1);
        }

        dup2(pts, 0);
        dup2(pts, 1);
        dup2(pts, 2);

        adb_close(pts);
        adb_close(ptm);

        // set OOM adjustment to zero
        char text[64];
        snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid());
        int fd = adb_open(text, O_WRONLY);
        if (fd >= 0) {
            adb_write(fd, "0", 1);
            adb_close(fd);
        } else {
           D("adb: unable to open %s\n", text);
           XLOGW("adb: unable to open %s\n", text);
        }

        timer_t timerid;
        struct sigevent sev;
        /* Create the timer */
        sev.sigev_notify = SIGEV_SIGNAL;
        sev.sigev_signo = SIGALRM;
        sev.sigev_value.sival_ptr = &timerid;
        if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1)
        {
            D("adb: Call timer_create failed!\n");
            XLOGV("adb: Call timer_create failed!\n");
            exit(-1);
        }

        struct itimerspec its;
        /* Start the timer */
        its.it_value.tv_sec = 1;
        its.it_value.tv_nsec = 0;
        its.it_interval.tv_sec = 3;
        its.it_interval.tv_nsec = 0;

        if (timer_settime(timerid, 0, &its, NULL) == -1)
        {
            D("adb: Call timer_settime failed!\n");
            XLOGV("adb: Call timer_settime failed!\n");
            exit(-1);
        }

        sigset_t mask;
        struct sigaction sa;
        /* Establish handler for timer signal */
        sa.sa_flags = SA_SIGINFO;
        sa.sa_sigaction = catcher;
        sigemptyset(&sa.sa_mask);
        if (sigaction(SIGALRM, &sa, NULL) == -1)
        {
            D("adb: Call sigaction failed!\n");
            XLOGV("adb: Call sigaction failed!\n");
            exit(-1);
        }

        int nRet = execl(cmd, cmd, arg0, arg1, NULL);

        fprintf(stderr, "- exec '%s' failed: %s (%d) nRet(%d) -\n",
                cmd, strerror(errno), errno, nRet);
        XLOGV("- exec '%s' failed: %s (%d) nRet(%d) -\n",
                cmd, strerror(errno), errno, nRet);
        exit(-1);
    } else {
        // Don't set child's OOM adjustment to zero.
        // Let the child do it itself, as sometimes the parent starts
        // running before the child has a /proc/pid/oom_adj.
        // """adb: unable to open /proc/644/oom_adj""" seen in some logs.
        return ptm;
    }
#endif /* !HAVE_WIN32_PROC */
}
Beispiel #29
0
int service_to_fd(const char *name)
{
    int ret = -1;

#if !ADB_HOST
    XLOGV("service_to_fd() name=%s\n", name);
#endif

    if(!strncmp(name, "tcp:", 4)) {
        int port = atoi(name + 4);
        name = strchr(name + 4, ':');
        if(name == 0) {
            ret = socket_loopback_client(port, SOCK_STREAM);
            if (ret >= 0)
                disable_tcp_nagle(ret);
        } else {
#if ADB_HOST
            adb_mutex_lock(&dns_lock);
            ret = socket_network_client(name + 1, port, SOCK_STREAM);
            adb_mutex_unlock(&dns_lock);
#else
            return -1;
#endif
        }
#ifndef HAVE_WINSOCK   /* winsock doesn't implement unix domain sockets */
    } else if(!strncmp(name, "local:", 6)) {
        ret = socket_local_client(name + 6,
                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    } else if(!strncmp(name, "localreserved:", 14)) {
        ret = socket_local_client(name + 14,
                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    } else if(!strncmp(name, "localabstract:", 14)) {
        ret = socket_local_client(name + 14,
                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
    } else if(!strncmp(name, "localfilesystem:", 16)) {
        ret = socket_local_client(name + 16,
                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
#endif
#if ADB_HOST
    } else if(!strncmp("dns:", name, 4)){
        char *n = strdup(name + 4);
        if(n == 0) return -1;
        ret = create_service_thread(dns_service, n);
#else /* !ADB_HOST */
    } else if(!strncmp("dev:", name, 4)) {
        ret = unix_open(name + 4, O_RDWR);
    } else if(!strncmp(name, "framebuffer:", 12)) {
        ret = create_service_thread(framebuffer_service, 0);
    } else if(recovery_mode && !strncmp(name, "recover:", 8)) {
        ret = create_service_thread(recover_service, (void*) atoi(name + 8));
    } else if (!strncmp(name, "jdwp:", 5)) {
        ret = create_jdwp_connection_fd(atoi(name+5));
    } else if (!strncmp(name, "log:", 4)) {
        ret = create_service_thread(log_service, get_log_file_path(name + 4));
    } else if(!HOST && !strncmp(name, "shell:", 6)) {
        if(name[6]) {
            ret = create_subproc_thread(name + 6);
        } else {
            ret = create_subproc_thread(0);
        }
    } else if(!strncmp(name, "sync:", 5)) {
        ret = create_service_thread(file_sync_service, NULL);
    } else if(!strncmp(name, "remount:", 8)) {
        ret = create_service_thread(remount_service, NULL);
    } else if(!strncmp(name, "reboot:", 7)) {
        void* arg = strdup(name + 7);
        if(arg == 0) return -1;
        ret = create_service_thread(reboot_service, arg);
    } else if(!strncmp(name, "root:", 5)) {
        ret = create_service_thread(restart_root_service, NULL);
    } else if(!strncmp(name, "backup:", 7)) {
        char* arg = strdup(name+7);
        if (arg == NULL) return -1;
        ret = backup_service(BACKUP, arg);
    } else if(!strncmp(name, "restore:", 8)) {
        ret = backup_service(RESTORE, NULL);
    } else if(!strncmp(name, "tcpip:", 6)) {
        int port;
        if (sscanf(name + 6, "%d", &port) == 0) {
            port = 0;
        }
        ret = create_service_thread(restart_tcp_service, (void *)port);
    } else if(!strncmp(name, "usb:", 4)) {
        ret = create_service_thread(restart_usb_service, NULL);
#endif
#if 0
    } else if(!strncmp(name, "echo:", 5)){
        ret = create_service_thread(echo_service, 0);
#endif
    }
    if (ret >= 0) {
        close_on_exec(ret);
    }
    return ret;
}