system/adb: Replace NuttX special shell service with microADB builtin one
since the new libuv porting support uv_proccess_t now Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
parent
77382e7209
commit
29374c96c3
@ -136,19 +136,36 @@ config ADBD_FILE_SERVICE
|
||||
---help---
|
||||
Enable "adb ls/push/pull" feature.
|
||||
|
||||
config ADBD_FILE_SYMLINK
|
||||
bool "File service symlink support"
|
||||
default n
|
||||
depends on ADBD_FILE_SERVICE
|
||||
depends on PSEUDOFS_SOFTLINKS
|
||||
---help---
|
||||
Enable fs symlink support.
|
||||
|
||||
config ADBD_SHELL_SERVICE
|
||||
bool "ADB shell support"
|
||||
depends on NSH_CONSOLE
|
||||
depends on SYSTEM_NSH
|
||||
select LIBC_EXECFUNCS
|
||||
select PSEUDOTERM
|
||||
default n
|
||||
---help---
|
||||
Enable "adb shell" feature.
|
||||
|
||||
config ADBD_FILE_SYMLINK
|
||||
bool "File service symlink support"
|
||||
default n
|
||||
depends on PSEUDOFS_SOFTLINKS
|
||||
config ADBD_SHELL_SERVICE_CMD
|
||||
string "ADB shell command"
|
||||
depends on ADBD_SHELL_SERVICE
|
||||
default "sh"
|
||||
---help---
|
||||
Enable fs symlink support.
|
||||
The shell command name.
|
||||
|
||||
config ADBD_SHELL_SERVICE_PATH
|
||||
string "ADB shell path"
|
||||
depends on ADBD_SHELL_SERVICE
|
||||
default "/bin/sh"
|
||||
---help---
|
||||
The path to the shell executable.
|
||||
|
||||
config ADBD_BOARD_INIT
|
||||
bool "Board initialization"
|
||||
|
@ -76,8 +76,7 @@ CSRCS += logcat_service.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADBD_SHELL_SERVICE),y)
|
||||
CSRCS += shell_service.c
|
||||
CSRCS += shell_pipe.c
|
||||
CSRCS += $(ADB_UNPACKNAME)/hal/shell_service_uv.c
|
||||
endif
|
||||
|
||||
context:: $(ADB_UNPACKDIR)
|
||||
|
@ -1,259 +0,0 @@
|
||||
/****************************************************************************
|
||||
* apps/system/adb/shell_pipe.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <uv.h>
|
||||
#include <unistd.h>
|
||||
#include "adb.h"
|
||||
#include "shell_pipe.h"
|
||||
#include "hal/hal_uv_priv.h"
|
||||
|
||||
#include <nshlib/nshlib.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void shell_on_data_available(uv_poll_t * handle,
|
||||
int status, int events)
|
||||
{
|
||||
int ret;
|
||||
apacket_uv_t *ap;
|
||||
shell_pipe_t *pipe = container_of(handle, shell_pipe_t, handle);
|
||||
|
||||
adb_client_t *client = (adb_client_t *)pipe->handle.data;
|
||||
|
||||
if (status)
|
||||
{
|
||||
adb_log("status error %d\n", status);
|
||||
|
||||
/* FIXME missing logic here */
|
||||
|
||||
pipe->on_data_cb(pipe, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
ap = adb_uv_packet_allocate((adb_client_uv_t *)client, 0);
|
||||
if (ap == NULL)
|
||||
{
|
||||
/* frame allocation failed. Try again later */
|
||||
|
||||
uv_poll_stop(&pipe->handle);
|
||||
return;
|
||||
}
|
||||
|
||||
int nread = 0;
|
||||
do
|
||||
{
|
||||
ret = read(handle->io_watcher.fd, &ap->p.data[nread], 1);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
/* EOF */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
/* Revisit. EAGAIN should not happen but it happens a lot */
|
||||
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
if (nread <= 0)
|
||||
{
|
||||
adb_hal_apacket_release(
|
||||
(adb_client_t *)pipe->handle.data, &ap->p);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Release packet and forward error */
|
||||
|
||||
adb_hal_apacket_release((adb_client_t *)pipe->handle.data, &ap->p);
|
||||
pipe->on_data_cb(pipe, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME CR LF conversion */
|
||||
|
||||
if (ap->p.data[nread++] == '\n')
|
||||
{
|
||||
ap->p.data[nread++] = '\r';
|
||||
}
|
||||
}
|
||||
while (nread < CONFIG_ADBD_PAYLOAD_SIZE - 1);
|
||||
|
||||
ap->p.msg.data_length = nread;
|
||||
pipe->on_data_cb(pipe, &ap->p);
|
||||
}
|
||||
|
||||
static void shell_pipe_close_callback(uv_handle_t *handle)
|
||||
{
|
||||
shell_pipe_t *pipe = container_of(handle, shell_pipe_t, handle);
|
||||
|
||||
/* Close stdout pipe */
|
||||
|
||||
close(pipe->write_fd);
|
||||
|
||||
/* Notify caller pipe is closed */
|
||||
|
||||
pipe->close_cb(pipe);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int shell_pipe_setup(adb_client_t *client, shell_pipe_t *apipe)
|
||||
{
|
||||
apipe->handle.data = client;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shell_pipe_destroy(shell_pipe_t *pipe, void (*close_cb)(shell_pipe_t *))
|
||||
{
|
||||
pipe->close_cb = close_cb;
|
||||
close(pipe->write_fd);
|
||||
|
||||
if (uv_fileno((const uv_handle_t *)&pipe->handle, &pipe->write_fd))
|
||||
{
|
||||
pipe->write_fd = -1;
|
||||
}
|
||||
|
||||
uv_close((uv_handle_t *)&pipe->handle, shell_pipe_close_callback);
|
||||
}
|
||||
|
||||
int shell_pipe_write(shell_pipe_t *pipe, const void *buf, size_t count)
|
||||
{
|
||||
/* TODO revisit */
|
||||
|
||||
return write(pipe->write_fd, buf, count);
|
||||
}
|
||||
|
||||
int shell_pipe_start(shell_pipe_t *pipe,
|
||||
void (*on_data_cb)(shell_pipe_t *, apacket *))
|
||||
{
|
||||
pipe->on_data_cb = on_data_cb;
|
||||
return uv_poll_start(&pipe->handle, UV_READABLE, shell_on_data_available);
|
||||
}
|
||||
|
||||
int shell_pipe_exec(char * const argv[], shell_pipe_t *apipe,
|
||||
void (*on_data_cb)(shell_pipe_t *, apacket *))
|
||||
{
|
||||
int ret;
|
||||
int in_fds[2];
|
||||
int out_fds[2];
|
||||
|
||||
adb_client_uv_t *client = (adb_client_uv_t *)apipe->handle.data;
|
||||
|
||||
/* Create pipe for stdin */
|
||||
|
||||
if ((ret = pipe(in_fds)))
|
||||
{
|
||||
adb_log("failed to open in pipe %d\n", errno);
|
||||
goto exit_fail;
|
||||
}
|
||||
|
||||
if ((ret = pipe(out_fds)))
|
||||
{
|
||||
adb_log("failed to open out pipe %d\n", errno);
|
||||
goto exit_close_pipe_in;
|
||||
}
|
||||
|
||||
apipe->write_fd = in_fds[1];
|
||||
|
||||
/* Setup stdout (read: adb, write: child) */
|
||||
|
||||
ret = dup2(out_fds[1], 1);
|
||||
assert(ret == 1);
|
||||
|
||||
ret = close(out_fds[1]);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = fcntl(out_fds[0], F_GETFD);
|
||||
assert(ret >= 0);
|
||||
ret = fcntl(out_fds[0], F_SETFD, ret | FD_CLOEXEC);
|
||||
assert(ret == 0);
|
||||
ret = fcntl(out_fds[0], F_GETFL);
|
||||
assert(ret >= 0);
|
||||
ret = fcntl(out_fds[0], F_SETFL, ret | O_NONBLOCK);
|
||||
assert(ret >= 0);
|
||||
|
||||
/* Setup stdin */
|
||||
|
||||
ret = dup2(in_fds[0], 0);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = close(in_fds[0]);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = fcntl(in_fds[1], F_GETFD);
|
||||
assert(ret >= 0);
|
||||
ret = fcntl(in_fds[1], F_SETFD, ret | FD_CLOEXEC);
|
||||
assert(ret == 0);
|
||||
ret = fcntl(in_fds[1], F_GETFL);
|
||||
assert(ret >= 0);
|
||||
ret = fcntl(in_fds[1], F_SETFL, ret | O_NONBLOCK);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = uv_poll_init(
|
||||
adb_uv_get_client_handle(client)->loop,
|
||||
&apipe->handle, out_fds[0]);
|
||||
|
||||
/* TODO check return code */
|
||||
|
||||
assert(ret == 0);
|
||||
|
||||
/* Create shell process */
|
||||
|
||||
ret = task_create("ADB shell", CONFIG_SYSTEM_NSH_PRIORITY,
|
||||
CONFIG_SYSTEM_NSH_STACKSIZE,
|
||||
argv ? nsh_system : nsh_consolemain,
|
||||
argv);
|
||||
|
||||
/* Close stdin and stdout */
|
||||
|
||||
dup2(2, 0);
|
||||
dup2(2, 1);
|
||||
|
||||
/* TODO check return code */
|
||||
|
||||
assert(ret >= 0);
|
||||
|
||||
/* Start listening shell process stdout */
|
||||
|
||||
ret = shell_pipe_start(apipe, on_data_cb);
|
||||
|
||||
/* TODO check return code */
|
||||
|
||||
assert(ret == 0);
|
||||
return 0;
|
||||
|
||||
exit_close_pipe_in:
|
||||
close(in_fds[0]);
|
||||
close(in_fds[1]);
|
||||
exit_fail:
|
||||
return ret;
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/****************************************************************************
|
||||
* apps/system/adb/shell_pipe.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <uv.h>
|
||||
#include "adb.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private types
|
||||
****************************************************************************/
|
||||
|
||||
struct shell_pipe_s
|
||||
{
|
||||
uv_poll_t handle;
|
||||
int write_fd;
|
||||
void (*close_cb)(struct shell_pipe_s *);
|
||||
void (*on_data_cb)(struct shell_pipe_s *, struct apacket_s *);
|
||||
};
|
||||
|
||||
typedef struct shell_pipe_s shell_pipe_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
int shell_pipe_setup(adb_client_t *client, shell_pipe_t *pipe);
|
||||
int shell_pipe_start(shell_pipe_t *pipe,
|
||||
void (*on_data_cb)(shell_pipe_t *, apacket *));
|
||||
void shell_pipe_destroy(shell_pipe_t *pipe,
|
||||
void (*close_cb)(shell_pipe_t *));
|
||||
int shell_pipe_write(shell_pipe_t *pipe, const void *buf, size_t count);
|
||||
|
||||
int shell_pipe_exec(char * const argv[], shell_pipe_t *pipe,
|
||||
void (*on_data_cb)(shell_pipe_t *, apacket *));
|
||||
int shell_exec_builtin(const char *appname, FAR char *const *argv,
|
||||
shell_pipe_t *apipe);
|
@ -1,212 +0,0 @@
|
||||
/****************************************************************************
|
||||
* apps/system/adb/shell_service.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "adb.h"
|
||||
#include "shell_service.h"
|
||||
#include "shell_pipe.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private types
|
||||
****************************************************************************/
|
||||
|
||||
typedef struct ash_service_s
|
||||
{
|
||||
adb_service_t service;
|
||||
shell_pipe_t pipe;
|
||||
adb_client_t *client;
|
||||
} ash_service_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static void exec_on_data_available(shell_pipe_t * pipe, apacket * p);
|
||||
|
||||
static int shell_ack(adb_service_t *service, apacket *p);
|
||||
static int shell_write(adb_service_t *service, apacket *p);
|
||||
static void shell_close(struct adb_service_s *service);
|
||||
static void shell_kick(adb_service_t *service);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void exec_on_data_available(shell_pipe_t * pipe, apacket * p)
|
||||
{
|
||||
ash_service_t *service = container_of(pipe, ash_service_t, pipe);
|
||||
|
||||
if (p->msg.data_length <= 0)
|
||||
{
|
||||
/* Got EOF */
|
||||
|
||||
adb_service_close(service->client, &service->service, p);
|
||||
return;
|
||||
}
|
||||
|
||||
p->write_len = p->msg.data_length;
|
||||
p->msg.arg0 = service->service.id;
|
||||
p->msg.arg1 = service->service.peer_id;
|
||||
adb_send_data_frame(service->client, p);
|
||||
}
|
||||
|
||||
static int shell_write(adb_service_t *service, apacket *p)
|
||||
{
|
||||
int ret;
|
||||
ash_service_t *svc = container_of(service, ash_service_t, service);
|
||||
UNUSED(svc);
|
||||
|
||||
if (p->msg.data_length <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = shell_pipe_write(&svc->pipe, p->data, p->msg.data_length);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
/* Shell process terminated, close service */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(ret == p->msg.data_length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_ack(adb_service_t *service, apacket *p)
|
||||
{
|
||||
UNUSED(service);
|
||||
UNUSED(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shell_kick(adb_service_t *service)
|
||||
{
|
||||
int ret;
|
||||
ash_service_t *svc = container_of(service, ash_service_t, service);
|
||||
ret = shell_pipe_start(&svc->pipe, exec_on_data_available);
|
||||
|
||||
/* TODO handle return code */
|
||||
|
||||
assert(ret == 0);
|
||||
}
|
||||
|
||||
static void shell_on_close(shell_pipe_t *pipe)
|
||||
{
|
||||
ash_service_t *svc = container_of(pipe, ash_service_t, pipe);
|
||||
free(svc);
|
||||
}
|
||||
|
||||
static void shell_close(adb_service_t *service)
|
||||
{
|
||||
ash_service_t *svc = container_of(service, ash_service_t, service);
|
||||
|
||||
/* FIXME missing logic here if shell process is still running */
|
||||
|
||||
shell_pipe_destroy(&svc->pipe, shell_on_close);
|
||||
}
|
||||
|
||||
static const adb_service_ops_t shell_ops =
|
||||
{
|
||||
.on_write_frame = shell_write,
|
||||
.on_ack_frame = shell_ack,
|
||||
.on_kick = shell_kick,
|
||||
.close = shell_close
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
adb_service_t * shell_service(adb_client_t *client, const char *params)
|
||||
{
|
||||
UNUSED(params);
|
||||
UNUSED(client);
|
||||
|
||||
int ret;
|
||||
char **argv;
|
||||
const char *target;
|
||||
ash_service_t *service =
|
||||
(ash_service_t *)malloc(sizeof(ash_service_t));
|
||||
|
||||
if (service == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
service->client = client;
|
||||
service->service.ops = &shell_ops;
|
||||
|
||||
ret = shell_pipe_setup(client, &service->pipe);
|
||||
|
||||
/* TODO check return code */
|
||||
|
||||
assert(ret == 0);
|
||||
|
||||
/* Check parameters after "shell:" */
|
||||
|
||||
target = ¶ms[6];
|
||||
|
||||
if (target[0] != 0)
|
||||
{
|
||||
/* Build argv: <nsh -c "command">
|
||||
* argv[0] => "-c"
|
||||
* argv[1] => command
|
||||
* argv[2] => NULL
|
||||
*
|
||||
* malloc content:
|
||||
* - x3 argv pointers
|
||||
* - 3 characters: "-c\0"
|
||||
* - space for command string
|
||||
*/
|
||||
|
||||
argv = malloc(sizeof(char *) * 3 + 3 + (strlen(target)+1));
|
||||
|
||||
argv[0] = (char *)&argv[3];
|
||||
argv[1] = &((char *)&argv[3])[3];
|
||||
argv[2] = NULL;
|
||||
strcpy(argv[0], "-c");
|
||||
strcpy(argv[1], target);
|
||||
}
|
||||
else
|
||||
{
|
||||
argv = NULL;
|
||||
}
|
||||
|
||||
ret = shell_pipe_exec(argv, &service->pipe,
|
||||
exec_on_data_available);
|
||||
|
||||
free(argv);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
adb_log("failed to setup shell pipe %d\n", ret);
|
||||
free(service);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &service->service;
|
||||
}
|
Loading…
Reference in New Issue
Block a user