diff --git a/BUILD.gn b/BUILD.gn index 240aedb5..c4adbc0a 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -27,18 +27,7 @@ # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -declare_args() { - enable_ohos_kernel_liteos_m_cppsupport = true - enable_ohos_kernel_liteos_m_cpup = true - enable_ohos_kernel_liteos_m_exchook = true - enable_ohos_kernel_liteos_m_kal = true - enable_ohos_kernel_liteos_m_fs = true - enable_ohos_kernel_liteos_m_backtrace = true - enable_ohos_kernel_liteos_m_test = false - enable_ohos_kernel_liteos_m_pm = true - enable_ohos_kernel_liteos_m_lwip = false - ohos_kernel_liteos_m_lwip_path = "components/net/lwip-2.1:lwip" -} +import("config.gni") group("kernel") { deps = [ @@ -67,6 +56,9 @@ group("kernel") { if (enable_ohos_kernel_liteos_m_kal == true) { deps += [ "kal:kal" ] } + if (enable_ohos_kernel_liteos_m_shell== true) { + deps += [ "components/shell:shell" ] + } if (enable_ohos_kernel_liteos_m_test == true) { deps += [ "testsuits:test" ] } diff --git a/components/net/lwip-2.1/lwip_porting.gni b/components/net/lwip-2.1/lwip_porting.gni index a57caa09..88f91f51 100644 --- a/components/net/lwip-2.1/lwip_porting.gni +++ b/components/net/lwip-2.1/lwip_porting.gni @@ -25,7 +25,7 @@ # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - +import("//kernel/liteos_m/config.gni") LWIP_PORTING_DIR = "//kernel/liteos_m/components/net/lwip-2.1" LWIP_PORTING_INCLUDE_DIRS = [ "$LWIP_PORTING_DIR/porting/include" ] @@ -36,6 +36,8 @@ LWIP_PORTING_FILES = [ "$LWIP_PORTING_DIR/porting/src/netdb_porting.c", "$LWIP_PORTING_DIR/porting/src/sockets_porting.c", "$LWIP_PORTING_DIR/porting/src/sys_arch.c", - + if (enable_ohos_kernel_liteos_m_shell== true) { + "$LWIP_PORTING_DIR/porting/src/api_shell.c", + } "$LWIP_PORTING_DIR/enhancement/src/fixme.c", ] \ No newline at end of file diff --git a/components/net/lwip-2.1/porting/include/lwip/api_shell.h b/components/net/lwip-2.1/porting/include/lwip/api_shell.h new file mode 100644 index 00000000..9983807f --- /dev/null +++ b/components/net/lwip-2.1/porting/include/lwip/api_shell.h @@ -0,0 +1,55 @@ +/********************************************************************************** + +* Copyright (c) <2013-2015>, +* All rights reserved. +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation and/or +* other materials provided with the distribution. +* Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software without +* specific prior written permission. +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************/ +/********************************************************************************** + +* Notice of Export Control Law +=============================================== +* Huawei LiteOS may be subject to applicable export control laws and regulations, which +* might include those applicable to Huawei LiteOS of U.S. and the country in which you +* are located. +* Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance +* with such applicable export control laws and regulations. +***********************************************************************************/ + + +#ifndef LWIP_API_SHELL_H +#define LWIP_API_SHELL_H + +#include "arch/cc.h" +#include "lwip/opt.h" + +#if defined (__cplusplus) && __cplusplus +extern "C" { +#endif + +u32_t lwip_ifconfig(int argc, const char **argv); +u32_t OsShellPing(int argc, const char **argv); +LWIP_STATIC int OsPingFunc(u32_t *parg); + +#if defined (__cplusplus) && __cplusplus +} +#endif +#endif /* LWIP_HDR_API_SHELL_H */ diff --git a/components/net/lwip-2.1/porting/src/api_shell.c b/components/net/lwip-2.1/porting/src/api_shell.c new file mode 100644 index 00000000..1e4b968b --- /dev/null +++ b/components/net/lwip-2.1/porting/src/api_shell.c @@ -0,0 +1,621 @@ +/********************************************************************************** + +* Copyright (c) <2013-2015>, +* All rights reserved. +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, this +* list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation and/or +* other materials provided with the distribution. +* Neither the name of the copyright holder nor the names of its contributors +* may be used to endorse or promote products derived from this software without +* specific prior written permission. +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************/ +/********************************************************************************** + +* Notice of Export Control Law +=============================================== +* Huawei LiteOS may be subject to applicable export control laws and regulations, which +* might include those applicable to Huawei LiteOS of U.S. and the country in which you +* are located. +* Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance +* with such applicable export control laws and regulations. +***********************************************************************************/ + + +#define LWIP_STATIC static +#define DHCP_STATE_OFF 0 +#define LWIP_EXT_POLL_SUPPORT 1 + +#include "lwip/api.h" +#include "lwip/netdb.h" +#include "lwip/stats.h" +#include "lwip/err.h" +#include "lwip/ip_addr.h" +#include "lwip/icmp.h" +#include "los_config.h" +#include +#include "lwip/api_shell.h" + +#include "shcmd.h" +#include "shell.h" +#include "los_timer_pri.h" +#include "los_debug.h" +#include "los_task.h" + +/* Forward Declarations [START] */ +#ifndef LWIP_TESTBED +LWIP_STATIC +#endif +int print_netif(struct netif *netif, char *print_buf, unsigned int buf_len); + +#ifndef LWIP_TESTBED +LWIP_STATIC +#endif +void lwip_ifconfig_show_internal(void *arg); + +#if LWIP_DNS +LWIP_STATIC unsigned int get_hostip(const char *hname); + +#ifndef LWIP_TESTBED +LWIP_STATIC +#endif +struct hostent *gethostnameinfo(const char *host, char *tmphstbuf, size_t hstbuflen); +#endif /* LWIP_DNS */ + +#define PRINT_BUF_LEN 1024 + +struct ifconfig_option { + char iface[IFNAMSIZ]; + unsigned int option; + ip_addr_t ip_addr; + ip_addr_t netmask; + ip_addr_t gw; + unsigned char ethaddr[6]; + u16_t mtu; + /* when using telnet, print to the telnet socket will result in system */ + /* deadlock. So we cahe the prinf data to a buf, and when the tcpip */ + /* callback returns, then print the data out to the telnet socket */ + sys_sem_t cb_completed; + char cb_print_buf[PRINT_BUF_LEN]; + unsigned int print_len; +}; + +#ifndef LWIP_TESTBED +LWIP_STATIC +#endif +int print_netif(struct netif *netif, char *print_buf, unsigned int buf_len) +{ + int i, ret; + char *tmp = print_buf; + + if (buf_len < 1) { + goto out; + } + if(netif->link_layer_type == LOOPBACK_IF){ + ret = snprintf_s(tmp, buf_len, (buf_len-1), "%s\t", netif->name); + } else { + ret = snprintf_s(tmp, buf_len, (buf_len-1), "%s%u\t", netif->name, netif->num); + } + + if ((ret <= 0) || ((unsigned int)ret >= buf_len)) + goto out; + tmp += ret; + buf_len -= (unsigned int)ret; +#if LWIP_IPV4 + ret = snprintf_s(tmp, buf_len, (buf_len - 1), "ip:%s ", ipaddr_ntoa(&netif->ip_addr)); + if ((ret <= 0) || ((unsigned int)ret >= buf_len)) + goto out; + tmp += ret; + buf_len -= (unsigned int)ret; + + ret = snprintf_s(tmp, buf_len, (buf_len - 1), "netmask:%s ", ipaddr_ntoa(&netif->netmask)); + if ((ret <= 0) || ((unsigned int)ret >= buf_len)) + goto out; + tmp += ret; + buf_len -= (unsigned int)ret; + + ret = snprintf_s(tmp, buf_len, (buf_len - 1), "gateway:%s\n", ipaddr_ntoa(&netif->gw)); + if ((ret <= 0) || ((unsigned int)ret >= buf_len)) + goto out; + tmp += ret; + buf_len -= (unsigned int)ret; +#endif + ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tHWaddr "); + if ((ret <= 0) || ((unsigned int)ret >= buf_len)) + goto out; + tmp += ret; + buf_len -= (unsigned int)ret; + + for (i = 0; i < netif->hwaddr_len - 1; i++) { + ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%02x:", netif->hwaddr[i]); + if ((ret <= 0) || ((unsigned int)ret >= buf_len)) + goto out; + tmp += ret; + buf_len -= (unsigned int)ret; + } + + ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%02x", netif->hwaddr[i]); + if ((ret <= 0) || ((unsigned int)ret >= buf_len)) + goto out; + tmp += ret; + buf_len -= (unsigned int)ret; + + ret = snprintf_s(tmp, buf_len, (buf_len - 1), " MTU:%d %s", netif->mtu, + netif->flags & NETIF_FLAG_UP ? "Running" : "Stop"); + if ((ret <= 0) || ((unsigned int)ret >= buf_len)) + goto out; + tmp += ret; + buf_len -= (unsigned int)ret; + + if (netif_default == netif && netif_is_up(netif)) { + ret = snprintf_s(tmp, buf_len, (buf_len - 1), " %s", "Default"); + if ((ret <= 0) || ((unsigned int)ret >= buf_len)) + goto out; + tmp += ret; + buf_len -= (unsigned int)ret; + } + + ret = snprintf_s(tmp, buf_len, (buf_len - 1), " %s\n", netif->flags & NETIF_FLAG_LINK_UP ? "Link UP" : "Link Down"); + if ((ret <= 0) || ((unsigned int)ret >= buf_len)) + goto out; + tmp += ret; + +out: + return (int)(tmp - print_buf); +} + +#ifndef LWIP_TESTBED +LWIP_STATIC +#endif +void lwip_ifconfig_show_internal(void *arg) +{ + struct netif *netif = NULL; + struct ifconfig_option *ifconfig_cmd = (struct ifconfig_option *)arg; + int ret; + + if (netif_list == NULL) { + ret = snprintf_s(ifconfig_cmd->cb_print_buf, PRINT_BUF_LEN - ifconfig_cmd->print_len, + ((PRINT_BUF_LEN - ifconfig_cmd->print_len) - 1), "Device not init\n"); + if ((ret > 0) && ((unsigned int)ret < (PRINT_BUF_LEN - ifconfig_cmd->print_len))) { + ifconfig_cmd->print_len += (unsigned int)ret; + } + sys_sem_signal(&ifconfig_cmd->cb_completed); + return; + } + + if (ifconfig_cmd->iface[0] == '\0') { + /* display all netif */ + for (netif = netif_list; netif != NULL; netif = netif->next) { + ret = print_netif(netif, ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len, + PRINT_BUF_LEN - ifconfig_cmd->print_len); + ifconfig_cmd->print_len += (unsigned int)ret; + } + } else { + netif = netif_find(ifconfig_cmd->iface); + if (netif == NULL) { + ret = snprintf_s(ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len, + (PRINT_BUF_LEN - ifconfig_cmd->print_len), + ((PRINT_BUF_LEN - ifconfig_cmd->print_len) - 1), "Device not found\n"); + if ((ret > 0) && ((unsigned int)ret < (PRINT_BUF_LEN - ifconfig_cmd->print_len))) { + ifconfig_cmd->print_len += (unsigned int)ret; + } + + sys_sem_signal(&ifconfig_cmd->cb_completed); + return; + } + + ret = print_netif(netif, ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len, + PRINT_BUF_LEN - ifconfig_cmd->print_len); + ifconfig_cmd->print_len += (unsigned int)ret; + } + sys_sem_signal(&ifconfig_cmd->cb_completed); +} + +/*lint -e838 -e438*/ +u32_t lwip_ifconfig(int argc, const char **argv) +{ + static struct ifconfig_option ifconfig_cmd; + err_t ret; + +#if LWIP_STATS + u32_t stat_err_cnt; + u32_t stat_drop_cnt; + u32_t stat_rx_or_tx_cnt; + u32_t stat_rx_or_tx_bytes; +#endif + + (void)memset_s(&ifconfig_cmd, sizeof(ifconfig_cmd), 0, sizeof(ifconfig_cmd)); + if (sys_sem_new(&ifconfig_cmd.cb_completed, 0) != ERR_OK) { + PRINTK("%s: sys_sem_new fail\n", __FUNCTION__); + return 1; + } + + /* Get the interface */ + + /* no more arguments, show all the interface state. */ + ret = tcpip_callback(lwip_ifconfig_show_internal, &ifconfig_cmd); + if (ret != ERR_OK) { + sys_sem_free(&ifconfig_cmd.cb_completed); + PRINTK("ifconfig : internal error, l:%d err:%d\n", __LINE__, ret); + return 1; + } + (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0); + sys_sem_free(&ifconfig_cmd.cb_completed); + ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0'; + PRINTK("%s", ifconfig_cmd.cb_print_buf); + + return 0; +} +/*lint +e838 +e438*/ + +#if LWIP_DNS +#ifndef LWIP_TESTBED +LWIP_STATIC +#endif +struct hostent *gethostnameinfo(const char *host, char *tmphstbuf, size_t hstbuflen) +{ + static struct hostent hostbuf; + struct hostent *hp = NULL; + int res; + int herr; + + if (tmphstbuf == NULL) + return NULL; + res = lwip_gethostbyname_r(host, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr); + /* Check for errors. */ + if (res || hp == NULL) { + return NULL; + } + return hp; +} + +LWIP_STATIC unsigned int get_hostip(const char *hname) +{ + unsigned int ip = 0; + int ret; + const size_t hstbuflen = 1024; + char *tmphstbuf = NULL; + + tmphstbuf = (char *)zalloc(sizeof(char) * hstbuflen); + if (tmphstbuf == NULL) + return 0; + + struct hostent *pent = gethostnameinfo(hname, tmphstbuf, hstbuflen); + if (pent == NULL || pent->h_addr == NULL) { + free(tmphstbuf); + return 0; + } + ret = memcpy_s(&ip, sizeof(ip), pent->h_addr, 4); + if (ret != 0) { + free(tmphstbuf); + return 0; + } + free(tmphstbuf); + return ip; +} + +#endif + +static int ping_taskid = -1; +static int ping_kill = 0; +#define LWIP_SHELL_CMD_PING_TIMEOUT 2000 +#define LWIP_SHELL_CMD_PING_RETRY_TIMES 4 +#define PING_ZERO_DATA_LEN 8 + +static void lwip_ping_usage(void) +{ + PRINTK("Usage:"\ + "\n ping [ip]\n" +} + +LWIP_STATIC int OsPingFunc(u32_t *parg) +{ + int sfd; + struct sockaddr_in to; + struct pbuf *pbuf_resp = NULL; + struct icmp_echo_hdr *iecho = NULL; + struct icmp_echo_hdr *iecho_resp = NULL; + struct ip_hdr *iphdr_resp = NULL; + u32_t iecho_len; + s16_t ip_hlen; + u32_t forever; + u32_t i = 0; + u32_t succ_cnt = 0; + u32_t failed_cnt = 0; + struct timespec start, end; + long timout_ms = 0; + struct pollfd pfd; + long rtt; + int ret = 0; + u32_t intrvl; + char *data_buf = NULL; + BOOL timeout_flag = false; + char buf[50]; + + u32_t destip = parg[0]; + u32_t cnt = parg[1]; + u32_t interval = parg[2]; + u32_t data_len = parg[3]; + + iecho_len = sizeof(struct icmp_echo_hdr) + data_len; + sfd = lwip_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); + if (sfd < 0) { + perror("Ping socket"); + return -1; + } + pbuf_resp = pbuf_alloc(PBUF_RAW, IP_HLEN + sizeof(struct icmp_echo_hdr), PBUF_RAM); + if (pbuf_resp == NULL) { + PRINTK("Ping: pbuf_resp malloc failed\n"); + ret = -1; + goto FAILURE; + } + iecho = (struct icmp_echo_hdr *)mem_malloc(iecho_len); + if (iecho == NULL) { + PRINTK("Ping: echo request malloc failed\n"); + ret = -1; + goto FAILURE; + } + + to.sin_family = AF_INET; + to.sin_addr.s_addr = destip; /* already in network order */ + to.sin_port = 0; + + if (data_len > PING_ZERO_DATA_LEN) { + (void)memset_s(iecho, sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN, + 0, sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN); + data_buf = (char *)iecho + sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN; + for (i = 0; i < data_len - PING_ZERO_DATA_LEN; i++) { + *(data_buf + i) = i + 0x10; + } + } else { + (void)memset_s(iecho, sizeof(struct icmp_echo_hdr) + data_len, 0, sizeof(struct icmp_echo_hdr) + data_len); + } + iecho->id = htons((u16_t)LOS_CurTaskIDGet()); + ICMPH_TYPE_SET(iecho, (u8_t)ICMP_ECHO); + forever = (cnt ? 0 : 1); + i = 0; + while (!ping_kill && (forever || (i < cnt))) { + iecho->seqno = htons((u16_t)i); + iecho->chksum = 0; + iecho->chksum = inet_chksum((void *)iecho, iecho_len); + + ret = sendto(sfd, iecho, iecho_len, 0, (struct sockaddr *)&to, (socklen_t)sizeof(to)); + if (ret < 0) { + perror("Ping: sending ICMP echo request failed\n"); + goto FAILURE; + } + + /* capture the start time to calculate RTT */ + (void)clock_gettime(CLOCK_MONOTONIC_RAW, &start); + + /* poll for ICMP echo response msg */ + pfd.fd = sfd; + + do { + pfd.events = POLLIN; + pfd.revents = 0; + timeout_flag = false; + ret = poll(&pfd, 1, LWIP_SHELL_CMD_PING_TIMEOUT); + if (ret < 0) { + perror("Ping: poll\n"); + goto FAILURE; + } else if (ret == 0) { + /* first type timeout event */ + timeout_flag = true; + break; + } + + ret = recv(sfd, pbuf_resp->payload, pbuf_resp->len, MSG_DONTWAIT); + if (ret < 0) { + perror("Ping: recv echo reply failed\n"); + goto FAILURE; + } + + /* Accessing ip header and icmp header */ + iphdr_resp = pbuf_resp->payload; + + ip_hlen = (IPH_HL(iphdr_resp) << 2); + if (pbuf_header(pbuf_resp, -ip_hlen)) { + /* this failure will never happen, but failure handle is written just to be in safe side */ + PRINTK("Ping : memory management failure\n"); + goto FAILURE; + } + iecho_resp = (struct icmp_echo_hdr *)pbuf_resp->payload; + /* Reverting back pbuf to its original state */ + if (pbuf_header(pbuf_resp, ip_hlen)) { + /* this failure will never happen, but failure handle is written just to be in safe side */ + PRINTK("ping : memory management failure\n"); + goto FAILURE; + } + + if ((iphdr_resp->src.addr != to.sin_addr.s_addr) || + ((ICMPH_TYPE(iecho_resp) == ICMP_ECHO) && (iphdr_resp->src.addr == to.sin_addr.s_addr))) { + /* second type timeout event */ + (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end); + timout_ms = ((end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000); + timout_ms = LWIP_SHELL_CMD_PING_TIMEOUT - timout_ms; + } else { + timout_ms = 0; + break; + } + } while (timout_ms >= 0); + + /* all timeout events are true timeout */ + if ((timout_ms < 0) || (timeout_flag == true)) { + failed_cnt++; + i++; + PRINTK("\nPing: destination unreachable ..."); + continue; + } + /* capture the end time to calculate round trip time */ + (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end); + rtt = ((end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000); + + if (iphdr_resp->src.addr == to.sin_addr.s_addr) { + switch (ICMPH_TYPE(iecho_resp)) { + case ICMP_ER: + PRINTK("\n[%u]Reply from %s: ", i, inet_ntop(AF_INET, &to.sin_addr, buf, sizeof(buf))); + if (rtt > 0) { + PRINTK("time=%ims ", rtt); + } else { + PRINTK("time<1ms "); + } + PRINTK("TTL=%u", iphdr_resp->_ttl); + + /* delay 1s for every successful ping */ + intrvl = interval; + do { + if (intrvl < 1000) { + sys_msleep(intrvl); + break; + } + intrvl -= 1000; + sys_msleep(1000); + if (ping_kill == 1) + break; + } while (intrvl > 0); + succ_cnt++; + break; + case ICMP_DUR: + PRINTK("\nPing: destination host unreachable ..."); + break; + case ICMP_SQ: + PRINTK("\nPing: source quench ..."); + break; + case ICMP_RD: + PRINTK("\nPing: redirect ..."); + break; + case ICMP_TE: + PRINTK("\nPing: time exceeded ..."); + break; + case ICMP_PP: + PRINTK("\nPing: parameter problem ..."); + break; + default: + PRINTK("\nPing: unknow error ..."); + break; + } + i++; + } + } + + PRINTK("\n--- %s ping statistics ---\n", inet_ntop(AF_INET, &to.sin_addr, buf, sizeof(buf))); + PRINTK("%u packets transmitted, %u received, %u loss\n", i, succ_cnt, failed_cnt); + +FAILURE: + ping_kill = 0; + (void)lwip_close(sfd); + if (pbuf_resp != NULL) { + (void)pbuf_free(pbuf_resp); + } + if (iecho != NULL) { + mem_free(iecho); + } + return ret; +} + +static void ping_cmd(u32_t *parg) +{ + int ret; + + ret = OsPingFunc(parg); + if (ret < 0) { + PRINTK("Ping cmd failed due to some errors\n"); + } + + ping_taskid = -1; +} + +u32_t OsShellPing(int argc, const char **argv) +{ + int ret; + u32_t i = 0; + u32_t count = 0; + int count_set = 0; + u32_t interval = 1000; /* default ping interval */ + u32_t data_len = 48; /* default data length */ + ip4_addr_t dst_ipaddr; + TSK_INIT_PARAM_S stPingTask; + u32_t *parg = NULL; + + if ((argc < 1) || (argv == NULL)) { + PRINTK("Ping: require dest ipaddr at least\n"); + goto ping_error; + } + + if (!count_set) { + count = LWIP_SHELL_CMD_PING_RETRY_TIMES; + } + + /* initialize dst IP address */ + if (argc <= 0) { + goto ping_error; + } +#if LWIP_DNS + dst_ipaddr.addr = get_hostip(argv[i]); +#endif /* LWIP_DNS */ + + if (dst_ipaddr.addr == IPADDR_NONE || dst_ipaddr.addr == IPADDR_ANY) { + PRINTK("Invalid dest ipaddr: NONE or ANY\n"); + return LOS_NOK; + } + + parg = (u32_t *)malloc(4 * sizeof(int)); + if (parg == NULL) { + return LOS_NOK; + } + parg[0] = dst_ipaddr.addr; + parg[1] = count; + parg[2] = interval; + parg[3] = data_len; + + /* start one task if ping forever or ping count greater than 60 */ + if (count == 0 || count > LWIP_SHELL_CMD_PING_RETRY_TIMES) { + if (ping_taskid > 0) { + free(parg); + PRINTK("Ping task already running and only support one now\n"); + return LOS_NOK; + } + stPingTask.pfnTaskEntry = (TSK_ENTRY_FUNC)ping_cmd; + stPingTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + stPingTask.pcName = "ping_task"; + stPingTask.usTaskPrio = 8; /* higher than shell */ + stPingTask.uwResved = LOS_TASK_STATUS_DETACHED; + stPingTask.uwArg = (UINTPTR)parg; + ret = LOS_TaskCreate((UINT32 *)(&ping_taskid), &stPingTask); + if (ret != LOS_OK) { + free(parg); + PRINTK("ping_task create failed 0x%08x.\n", ret); + count = LWIP_SHELL_CMD_PING_RETRY_TIMES; + } else { + return LOS_OK; + } + } + + /* two cases: + 1, ping cout less than LWIP_SHELL_CMD_PING_RETRY_TIMES; + 2, ping task create failed; + */ + if (OsPingFunc(parg) < 0) { + PRINTK("Ping cmd failed due some errors\n"); + } + + return LOS_OK; +ping_error: + lwip_ping_usage(); + return LOS_NOK; +} + diff --git a/components/shell/BUILD.gn b/components/shell/BUILD.gn new file mode 100644 index 00000000..933ecd86 --- /dev/null +++ b/components/shell/BUILD.gn @@ -0,0 +1,55 @@ +# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. +# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("shell") { + sources = [ + "src/base/shcmd.c", + "src/base/shcmdparse.c", + "src/base/shmsg.c", + "src/base/show.c", + "src/cmds/date_shell.c", + "src/cmds/shell_shellcmd.c", + "src/cmds/task_shellcmd.c", + "src/cmds/vfs_shellcmd.c", + "src/cmds/mempt_shellcmd.c", + "src/cmds/fullpath.c", + ] + + include_dirs = [ + "../../kernel/arch/include", + "../../kernel/include", + "../../utils", + "./include", + ] + + deps = [ + "//kernel/liteos_m/kal/posix", + "//third_party/bounds_checking_function:libsec_static", + ] +} diff --git a/components/shell/include/shcmd.h b/components/shell/include/shcmd.h new file mode 100644 index 00000000..fe810f01 --- /dev/null +++ b/components/shell/include/shcmd.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _HWLITEOS_SHELL_SHCMD_H +#define _HWLITEOS_SHELL_SHCMD_H + +#include "string.h" +#include "stdlib.h" +#include "los_list.h" +#include "shcmdparse.h" +#include "show.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +typedef BOOL (*CmdVerifyTransID)(UINT32 transID); + +typedef struct { + CmdType cmdType; + const CHAR *cmdKey; + UINT32 paraNum; + CmdCallBackFunc cmdHook; +} CmdItem; + +typedef struct { + LOS_DL_LIST list; + CmdItem *cmd; +} CmdItemNode; + +/* global info for shell module */ +typedef struct { + CmdItemNode cmdList; + UINT32 listNum; + UINT32 initMagicFlag; + UINT32 muxLock; + CmdVerifyTransID transIdHook; +} CmdModInfo; + +typedef struct { + UINT32 count; + LOS_DL_LIST list; + CHAR cmdString[0]; +} CmdKeyLink; + +#define SHELLCMD_ENTRY(l, cmdType, cmdKey, paraNum, cmdHook) \ + CmdItem l LOS_HAL_TABLE_ENTRY(shellcmd) = { \ + cmdType, \ + cmdKey, \ + paraNum, \ + cmdHook \ + } + +#define NEED_NEW_LINE(timesPrint, lineCap) ((timesPrint) % (lineCap) == 0) +#define SCREEN_IS_FULL(timesPrint, lineCap) ((timesPrint) >= ((lineCap) * DEFAULT_SCREEN_HEIGNT)) + +extern CmdModInfo *OsCmdInfoGet(VOID); +extern UINT32 OsCmdExec(CmdParsed *cmdParsed, CHAR *cmdStr); +extern UINT32 OsCmdKeyShift(const CHAR *cmdKey, CHAR *cmdOut, UINT32 size); +extern UINT32 OsShellKeyInit(ShellCB *shellCB); +extern VOID OsShellKeyDeInit(CmdKeyLink *cmdKeyLink); +extern UINT32 OsShellSysCmdRegister(VOID); +extern int VfsNormalizePath(const char *directory, const char *filename, char **pathname); +extern INT32 OsShellCmdDate(INT32 argc, const CHAR **argv); +extern INT32 OsShellCmdDumpTask(INT32 argc, const CHAR **argv); +extern UINT32 OsShellCmdFree(INT32 argc, const CHAR **argv); +extern UINT32 lwip_ifconfig(INT32 argc, const CHAR **argv); +extern UINT32 OsShellPing(INT32 argc, const CHAR **argv); +extern INT32 OsShellCmdTouch(INT32 argc, const CHAR **argv); +extern INT32 OsShellCmdLs(INT32 argc, const CHAR **argv); +extern INT32 OsShellCmdPwd(INT32 argc, const CHAR **argv); +extern INT32 OsShellCmdCd(INT32 argc, const CHAR **argv); +extern INT32 OsShellCmdCat(INT32 argc, const CHAR **argv); +extern INT32 OsShellCmdRm(INT32 argc, const CHAR **argv); +extern INT32 OsShellCmdRmdir(INT32 argc, const CHAR **argv); +extern INT32 OsShellCmdMkdir(INT32 argc, const CHAR **argv); +extern INT32 OsShellCmdCp(INT32 argc, const CHAR **argv); +extern INT32 OsShellCmdHelp(INT32 argc, const CHAR **argv); + + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* _HWLITEOS_SHELL_SHCMD_H */ diff --git a/components/shell/include/shcmdparse.h b/components/shell/include/shcmdparse.h new file mode 100644 index 00000000..c3e77843 --- /dev/null +++ b/components/shell/include/shcmdparse.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _HWLITEOS_SHELL_SHCMDPARSE_H +#define _HWLITEOS_SHELL_SHCMDPARSE_H + +#include "string.h" +#include "show.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +#define CMD_PARSED_RETCODE_BASE LOS_OK +#define CMD_PARSED_RETCODE_TYPE_INVALID (CMD_PARSED_RETCODE_BASE + 1) +#define CMD_PARSED_RETCODE_PARAM_OVERTOP (CMD_PARSED_RETCODE_BASE + 3) +#define CMD_PARSED_RETCODE_CMDKEY_NOTFOUND (CMD_PARSED_RETCODE_BASE + 4) + +typedef UINT32 (*FUNC_ONE_TOKEN)(VOID *ctx, UINT32 index, CHAR *token); + +/* + * Description: the info struct after cmd parser + */ +typedef struct { + UINT32 paramCnt; /* count of para */ + CmdType cmdType; /* cmd type, judge cmd keyword */ + CHAR cmdKeyword[CMD_KEY_LEN]; /* cmd keyword str */ + CHAR *paramArray[CMD_MAX_PARAS]; +} CmdParsed; + +extern UINT32 OsCmdParse(CHAR *cmdStr, CmdParsed *cmdParsed); +extern CHAR *OsCmdParseStrdup(const CHAR *str); +extern UINT32 OsCmdParseOneToken(CmdParsed *cmdParsed, UINT32 index, const CHAR *token); +extern UINT32 OsCmdTokenSplit(CHAR *cmdStr, CHAR split, CmdParsed *cmdParsed); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif /* _HWLITEOS_SHELL_SHCMDPARSE_H */ diff --git a/components/shell/include/shell.h b/components/shell/include/shell.h new file mode 100644 index 00000000..2c41aed9 --- /dev/null +++ b/components/shell/include/shell.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _HWLITEOS_SHELL_H +#define _HWLITEOS_SHELL_H + +#include "pthread.h" +#include "limits.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define OS_ERRNO_SHELL_NO_HOOK LOS_ERRNO_OS_ERROR(LOS_MOD_SHELL, 0x00) +#define OS_ERRNO_SHELL_CMDREG_PARA_ERROR LOS_ERRNO_OS_ERROR(LOS_MOD_SHELL, 0x01) +#define OS_ERRNO_SHELL_CMDREG_CMD_ERROR LOS_ERRNO_OS_ERROR(LOS_MOD_SHELL, 0x02) +#define OS_ERRNO_SHELL_CMDREG_CMD_EXIST LOS_ERRNO_OS_ERROR(LOS_MOD_SHELL, 0x03) +#define OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR LOS_ERRNO_OS_ERROR(LOS_MOD_SHELL, 0x04) +#define OS_ERRNO_SHELL_SHOW_HOOK_NULL LOS_ERRNO_OS_ERROR(LOS_MOD_SHELL, 0x05) +#define OS_ERRNO_SHELL_SHOW_HOOK_EXIST LOS_ERRNO_OS_ERROR(LOS_MOD_SHELL, 0x06) +#define OS_ERRNO_SHELL_SHOW_HOOK_TOO_MUCH LOS_ERRNO_OS_ERROR(LOS_MOD_SHELL, 0x07) +#define OS_ERRNO_SHELL_NOT_INIT LOS_ERRNO_OS_ERROR(LOS_MOD_SHELL, 0x08) +#define OS_ERRNO_SHELL_CMD_HOOK_NULL LOS_ERRNO_OS_ERROR(LOS_MOD_SHELL, 0x09) +#define OS_ERRNO_SHELL_FIFO_ERROR LOS_ERRNO_OS_ERROR(LOS_MOD_SHELL, 0x10) + +/* Max len of show str */ +#define SHOW_MAX_LEN CMD_MAX_LEN + +#define XARGS 0xFFFFFFFF /* default args */ + +#define CMD_MAX_PARAS 32 +#define CMD_KEY_LEN 16U +#define CMD_MAX_LEN (256U + CMD_KEY_LEN) +#define CMD_KEY_NUM 32 +#define CMD_HISTORY_LEN 10 +#define CMD_MAX_PATH 256 +#define DEFAULT_SCREEN_WIDTH 80 +#define DEFAULT_SCREEN_HEIGNT 24 + +#define SHELL_MODE 0 +#define OTHER_MODE 1 + +#define SWITCH_QUOTES_STATUS(qu) do { \ + if ((qu) == TRUE) { \ + (qu) = FALSE; \ + } else { \ + (qu) = TRUE; \ + } \ +} while (0) + +#define QUOTES_STATUS_CLOSE(qu) ((qu) == FALSE) +#define QUOTES_STATUS_OPEN(qu) ((qu) == TRUE) + +typedef struct { + UINT32 consoleID; + UINT32 shellTaskHandle; + UINT32 shellEntryHandle; + VOID *cmdKeyLink; + VOID *cmdHistoryKeyLink; + VOID *cmdMaskKeyLink; + UINT32 shellBufOffset; + UINT32 shellKeyType; + EVENT_CB_S shellEvent; + pthread_mutex_t keyMutex; + pthread_mutex_t historyMutex; + CHAR shellBuf[SHOW_MAX_LEN]; + CHAR shellWorkingDirectory[PATH_MAX]; +} ShellCB; + +/* All support cmd types */ +typedef enum { + CMD_TYPE_SHOW = 0, + CMD_TYPE_STD = 1, + CMD_TYPE_EX = 2, + CMD_TYPE_BUTT +} CmdType; + +typedef enum { + CMD_KEY_UP = 0, + CMD_KEY_DOWN = 1, + CMD_KEY_RIGHT = 2, + CMD_KEY_LEFT = 4, + CMD_KEY_BUTT +} CmdKeyDirection; + +/* + * Hook for user-defined debug function + * Unify differnt module's func for registration + */ +typedef UINT32 (*CmdCallBackFunc)(UINT32 argc, const CHAR **argv); + +/* External interface, need reserved */ +typedef CmdCallBackFunc CMD_CBK_FUNC; +typedef CmdType CMD_TYPE_E; + +extern UINT32 osCmdReg(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _HWLITEOS_SHELL_H */ diff --git a/components/shell/include/shmsg.h b/components/shell/include/shmsg.h new file mode 100644 index 00000000..789a024b --- /dev/null +++ b/components/shell/include/shmsg.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _HWLITEOS_SHELL_SHMSG_H +#define _HWLITEOS_SHELL_SHMSG_H + +#include "shell.h" +#include "shcmdparse.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +extern UINT32 ShellMsgTypeGet(CmdParsed *cmdParsed, const CHAR *cmdType); +extern void ExecCmdline(const char *cmdline); + +#define SHELL_CMD_PARSE_EVENT 0x111 + +#define SH_OK 0 +#define SH_NOK 1 +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _HWLITEOS_SHELL_SHMSG_H */ diff --git a/components/shell/include/show.h b/components/shell/include/show.h new file mode 100644 index 00000000..7b05b8e9 --- /dev/null +++ b/components/shell/include/show.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _HWLITEOS_SHELL_SHOW_H +#define _HWLITEOS_SHELL_SHOW_H + +#include "shell.h" +#include "los_debug.h" +#include "errno.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +extern CHAR *OsShellGetWorkingDirtectory(VOID); +extern UINT32 OsShellInit(INT32 consoleId); +extern INT32 OsShellDeinit(INT32 consoleId); + +static inline void SetErrno(int errcode) +{ + errno = errcode; +} + +static inline void SetErr(int errcode, const char *errMessage) +{ + SetErrno(errcode); + PRINTK(errMessage); +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _HWLITEOS_SHELL_SHOW_H */ \ No newline at end of file diff --git a/components/shell/src/base/shcmd.c b/components/shell/src/base/shcmd.c new file mode 100755 index 00000000..544d29cc --- /dev/null +++ b/components/shell/src/base/shcmd.c @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "shcmd.h" +#include "show.h" +#include "shmsg.h" +#include "stdlib.h" +#include "unistd.h" +#include "dirent.h" +#include "securec.h" +#include "los_mux.h" +#include "los_memory.h" +#include "los_typedef.h" + +#define SHELL_INIT_MAGIC_FLAG 0xABABABAB + +STATIC CmdModInfo cmdInfo; +ShellCB *g_shellCB = NULL; +CmdItem g_shellcmdAll[] = { + {CMD_TYPE_STD, "date", XARGS, (CmdCallBackFunc)OsShellCmdDate}, + {CMD_TYPE_EX, "task", 1, (CmdCallBackFunc)OsShellCmdDumpTask}, + {CMD_TYPE_EX, "free", XARGS, (CmdCallBackFunc)OsShellCmdFree}, + {CMD_TYPE_EX, "ifconfig", XARGS, (CmdCallBackFunc)lwip_ifconfig}, + {CMD_TYPE_EX, "ping", XARGS, (CmdCallBackFunc)OsShellPing}, + {CMD_TYPE_EX, "touch", XARGS, (CmdCallBackFunc)OsShellCmdTouch}, + {CMD_TYPE_EX, "ls", XARGS, (CmdCallBackFunc)OsShellCmdLs}, + {CMD_TYPE_EX, "pwd", XARGS, (CmdCallBackFunc)OsShellCmdPwd}, + {CMD_TYPE_EX, "cd", XARGS, (CmdCallBackFunc)OsShellCmdCd}, + {CMD_TYPE_EX, "cat", XARGS, (CmdCallBackFunc)OsShellCmdCat}, + {CMD_TYPE_EX, "rm", XARGS, (CmdCallBackFunc)OsShellCmdRm}, + {CMD_TYPE_EX, "rmdir", XARGS, (CmdCallBackFunc)OsShellCmdRmdir}, + {CMD_TYPE_EX, "mkdir", XARGS, (CmdCallBackFunc)OsShellCmdMkdir}, + {CMD_TYPE_EX, "cp", XARGS, (CmdCallBackFunc)OsShellCmdCp}, + {CMD_TYPE_EX, "help", 0, (CmdCallBackFunc)OsShellCmdHelp}, +}; + +CmdModInfo *OsCmdInfoGet(VOID) +{ + return &cmdInfo; +} + +/* + * Description: Pass in the string and clear useless space ,which inlcude: + * 1) The overmatch space which is not be marked by Quote's area + * Squeeze the overmatch space into one space + * 2) Clear all space before first vaild charatctor + * Input: cmdKey : Pass in the buff string, which is ready to be operated + * cmdOut : Pass out the buffer string ,which has already been operated + * size : cmdKey length + */ +LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdKeyShift(const CHAR *cmdKey, CHAR *cmdOut, UINT32 size) +{ + CHAR *output = NULL; + CHAR *outputBak = NULL; + UINT32 len; + INT32 ret; + BOOL quotes = FALSE; + + if ((cmdKey == NULL) || (cmdOut == NULL)) { + return (UINT32)OS_ERROR; + } + + len = strlen(cmdKey); + if (len >= size) { + return (UINT32)OS_ERROR; + } + output = (CHAR*)LOS_MemAlloc(m_aucSysMem0, len + 1); + if (output == NULL) { + PRINTK("malloc failure in %s[%d]", __FUNCTION__, __LINE__); + return (UINT32)OS_ERROR; + } + /* Backup the 'output' start address */ + outputBak = output; + /* Scan each charactor in 'cmdKey',and squeeze the overmuch space and ignore invaild charactor */ + for (; *cmdKey != '\0'; cmdKey++) { + /* Detected a Double Quotes, switch the matching status */ + if (*(cmdKey) == '\"') { + SWITCH_QUOTES_STATUS(quotes); + } + /* Ignore the current charactor in following situation */ + /* 1) Quotes matching status is FALSE (which said that the space is not been marked by double quotes) */ + /* 2) Current charactor is a space */ + /* 3) Next charactor is a space too, or the string is been seeked to the end already(\0) */ + /* 4) Invaild charactor, such as single quotes */ + if ((*cmdKey == ' ') && ((*(cmdKey + 1) == ' ') || (*(cmdKey + 1) == '\0')) && QUOTES_STATUS_CLOSE(quotes)) { + continue; + } + if (*cmdKey == '\'') { + continue; + } + *output = *cmdKey; + output++; + } + *output = '\0'; + /* Restore the 'output' start address */ + output = outputBak; + len = strlen(output); + /* Clear the space which is located at the first charactor in buffer */ + if (*outputBak == ' ') { + output++; + len--; + } + /* Copy out the buffer which is been operated already */ + ret = strncpy_s(cmdOut, size, output, len); + if (ret != EOK) { + PRINT_ERR("%s,%d strncpy_s failed, err:%d!\n", __FUNCTION__, __LINE__, ret); + (VOID)LOS_MemFree(m_aucSysMem0, output); + return OS_ERROR; + } + cmdOut[len] = '\0'; + + (VOID)LOS_MemFree(m_aucSysMem0, output); + + return LOS_OK; +} + +LITE_OS_SEC_TEXT_MINOR BOOL OsCmdKeyCheck(const CHAR *cmdKey) +{ + const CHAR *temp = cmdKey; + enum Stat { + STAT_NONE, + STAT_DIGIT, + STAT_OTHER + } state = STAT_NONE; + + if (strlen(cmdKey) >= CMD_KEY_LEN) { + return FALSE; + } + + while (*temp != '\0') { + if (!((*temp <= '9') && (*temp >= '0')) && + !((*temp <= 'z') && (*temp >= 'a')) && + !((*temp <= 'Z') && (*temp >= 'A')) && + (*temp != '_') && (*temp != '-')) { + return FALSE; + } + + if ((*temp >= '0') && (*temp <= '9')) { + if (state == STAT_NONE) { + state = STAT_DIGIT; + } + } else { + state = STAT_OTHER; + } + + temp++; + } + + if (state == STAT_DIGIT) { + return FALSE; + } + + return TRUE; +} + +LITE_OS_SEC_TEXT_MINOR VOID OsCmdAscendingInsert(CmdItemNode *cmd) +{ + CmdItemNode *cmdItem = NULL; + CmdItemNode *cmdNext = NULL; + + if (cmd == NULL) { + return; + } + + for (cmdItem = LOS_DL_LIST_ENTRY((&cmdInfo.cmdList.list)->pstPrev, CmdItemNode, list); + &cmdItem->list != &(cmdInfo.cmdList.list);) { + cmdNext = LOS_DL_LIST_ENTRY(cmdItem->list.pstPrev, CmdItemNode, list); + if (&cmdNext->list != &(cmdInfo.cmdList.list)) { + if ((strncmp(cmdItem->cmd->cmdKey, cmd->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) >= 0) && + (strncmp(cmdNext->cmd->cmdKey, cmd->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) < 0)) { + LOS_ListTailInsert(&(cmdItem->list), &(cmd->list)); + return; + } + cmdItem = cmdNext; + } else { + if (strncmp(cmd->cmd->cmdKey, cmdItem->cmd->cmdKey, strlen(cmd->cmd->cmdKey)) > 0) { + cmdItem = cmdNext; + } + break; + } + } + + LOS_ListTailInsert(&(cmdItem->list), &(cmd->list)); +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsShellKeyInit(ShellCB *shellCB) +{ + CmdKeyLink *cmdKeyLink = NULL; + CmdKeyLink *cmdHistoryLink = NULL; + + if (shellCB == NULL) { + return OS_ERROR; + } + cmdKeyLink = (CmdKeyLink *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdKeyLink)); + if (cmdKeyLink == NULL) { + PRINT_ERR("Shell CmdKeyLink memory alloc error!\n"); + return OS_ERROR; + } + cmdHistoryLink = (CmdKeyLink *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdKeyLink)); + if (cmdHistoryLink == NULL) { + (VOID)LOS_MemFree(m_aucSysMem0, cmdKeyLink); + PRINT_ERR("Shell CmdHistoryLink memory alloc error!\n"); + return OS_ERROR; + } + + cmdKeyLink->count = 0; + LOS_ListInit(&(cmdKeyLink->list)); + shellCB->cmdKeyLink = (VOID *)cmdKeyLink; + + cmdHistoryLink->count = 0; + LOS_ListInit(&(cmdHistoryLink->list)); + shellCB->cmdHistoryKeyLink = (VOID *)cmdHistoryLink; + shellCB->cmdMaskKeyLink = (VOID *)cmdHistoryLink; + return LOS_OK; +} + +LITE_OS_SEC_TEXT_MINOR VOID OsShellKeyDeInit(CmdKeyLink *cmdKeyLink) +{ + CmdKeyLink *cmdtmp = NULL; + if (cmdKeyLink == NULL) { + return; + } + + while (!LOS_ListEmpty(&(cmdKeyLink->list))) { + cmdtmp = LOS_DL_LIST_ENTRY(cmdKeyLink->list.pstNext, CmdKeyLink, list); + LOS_ListDelete(&cmdtmp->list); + (VOID)LOS_MemFree(m_aucSysMem0, cmdtmp); + } + + cmdKeyLink->count = 0; + (VOID)LOS_MemFree(m_aucSysMem0, cmdKeyLink); +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsShellSysCmdRegister(VOID) +{ + UINT32 i; + UINT8 *cmdItemGroup = NULL; + UINT32 index = sizeof(g_shellcmdAll) / sizeof(CmdItem); + CmdItemNode *cmdItem = NULL; + + cmdItemGroup = (UINT8 *)LOS_MemAlloc(m_aucSysMem0, index * sizeof(CmdItemNode)); + if (cmdItemGroup == NULL) { + PRINT_ERR("[%s]System memory allocation failure!\n", __FUNCTION__); + return (UINT32)OS_ERROR; + } + + for (i = 0; i < index; ++i) { + cmdItem = (CmdItemNode *)(cmdItemGroup + i * sizeof(CmdItemNode)); + cmdItem->cmd = &g_shellcmdAll[i]; + OsCmdAscendingInsert(cmdItem); + } + cmdInfo.listNum += index; + return LOS_OK; +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdExec(CmdParsed *cmdParsed, CHAR *cmdStr) +{ + UINT32 ret; + CmdCallBackFunc cmdHook = NULL; + CmdItemNode *curCmdItem = NULL; + UINT32 i; + const CHAR *cmdKey = NULL; + + if ((cmdParsed == NULL) || (cmdStr == NULL) || (strlen(cmdStr) == 0)) { + return (UINT32)OS_ERROR; + } + + ret = OsCmdParse(cmdStr, cmdParsed); + if (ret != LOS_OK) { + goto OUT; + } + + LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(cmdInfo.cmdList.list), CmdItemNode, list) { + cmdKey = curCmdItem->cmd->cmdKey; + if ((cmdParsed->cmdType == curCmdItem->cmd->cmdType) && + (strlen(cmdKey) == strlen(cmdParsed->cmdKeyword)) && + (strncmp(cmdKey, (CHAR *)(cmdParsed->cmdKeyword), strlen(cmdKey)) == 0)) { + cmdHook = curCmdItem->cmd->cmdHook; + break; + } + } + + ret = OS_ERROR; + if (cmdHook != NULL) { + ret = (cmdHook)(cmdParsed->paramCnt, (const CHAR **)cmdParsed->paramArray); + } + +OUT: + for (i = 0; i < cmdParsed->paramCnt; i++) { + if (cmdParsed->paramArray[i] != NULL) { + (VOID)LOS_MemFree(m_aucSysMem0, cmdParsed->paramArray[i]); + cmdParsed->paramArray[i] = NULL; + } + } + + return (UINT32)ret; +} + +ShellCB *OsGetShellCb(VOID) + +{ + return g_shellCB; +} + +char *OsShellGetWorkingDirtectory(VOID) +{ + return OsGetShellCb()->shellWorkingDirectory; +} + +VOID OsShellCBInit(VOID) +{ + int ret; + ShellCB *shellCB = NULL; + + shellCB = (ShellCB *)malloc(sizeof(ShellCB)); + if (shellCB == NULL) { + goto ERR_OUT1; + } + ret = memset_s(shellCB, sizeof(ShellCB), 0, sizeof(ShellCB)); + if (ret != SH_OK) { + goto ERR_OUT1; + } + + ret = (int)OsShellKeyInit(shellCB); + if (ret != SH_OK) { + goto ERR_OUT1; + } + (void)strncpy_s(shellCB->shellWorkingDirectory, PATH_MAX, "/", 2); /* 2:space for "/" */ + + g_shellCB = shellCB; + return; + +ERR_OUT1: + (void)free(shellCB); + return; +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdInit(VOID) +{ + UINT32 ret; + LOS_ListInit(&(cmdInfo.cmdList.list)); + cmdInfo.listNum = 0; + cmdInfo.initMagicFlag = SHELL_INIT_MAGIC_FLAG; + ret = LOS_MuxCreate(&cmdInfo.muxLock); + if (ret != LOS_OK) { + PRINT_ERR("Create mutex for shell cmd info failed\n"); + return OS_ERROR; + } + OsShellCBInit(); + + return LOS_OK; +} + +STATIC UINT32 OsCmdItemCreate(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc) +{ + CmdItem *cmdItem = NULL; + CmdItemNode *cmdItemNode = NULL; + + cmdItem = (CmdItem *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdItem)); + if (cmdItem == NULL) { + return OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR; + } + (VOID)memset_s(cmdItem, sizeof(CmdItem), '\0', sizeof(CmdItem)); + + cmdItemNode = (CmdItemNode *)LOS_MemAlloc(m_aucSysMem0, sizeof(CmdItemNode)); + if (cmdItemNode == NULL) { + (VOID)LOS_MemFree(m_aucSysMem0, cmdItem); + return OS_ERRNO_SHELL_CMDREG_MEMALLOC_ERROR; + } + (VOID)memset_s(cmdItemNode, sizeof(CmdItemNode), '\0', sizeof(CmdItemNode)); + cmdItemNode->cmd = cmdItem; + cmdItemNode->cmd->cmdHook = cmdProc; + cmdItemNode->cmd->paraNum = paraNum; + cmdItemNode->cmd->cmdType = cmdType; + cmdItemNode->cmd->cmdKey = cmdKey; + + (VOID)LOS_MuxPend(cmdInfo.muxLock, LOS_WAIT_FOREVER); + OsCmdAscendingInsert(cmdItemNode); + cmdInfo.listNum++; + (VOID)LOS_MuxPost(cmdInfo.muxLock); + + return LOS_OK; +} + +/* open API */ +LITE_OS_SEC_TEXT_MINOR UINT32 osCmdReg(CmdType cmdType, const CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc) +{ + CmdItemNode *cmdItemNode = NULL; + + (VOID)LOS_MuxPend(cmdInfo.muxLock, LOS_WAIT_FOREVER); + if (cmdInfo.initMagicFlag != SHELL_INIT_MAGIC_FLAG) { + (VOID)LOS_MuxPost(cmdInfo.muxLock); + PRINT_ERR("[%s] shell is not yet initialized!\n", __FUNCTION__); + return OS_ERRNO_SHELL_NOT_INIT; + } + (VOID)LOS_MuxPost(cmdInfo.muxLock); + + if ((cmdProc == NULL) || (cmdKey == NULL) || + (cmdType >= CMD_TYPE_BUTT) || (strlen(cmdKey) >= CMD_KEY_LEN) || !strlen(cmdKey)) { + return OS_ERRNO_SHELL_CMDREG_PARA_ERROR; + } + + if (paraNum > CMD_MAX_PARAS) { + if (paraNum != XARGS) { + return OS_ERRNO_SHELL_CMDREG_PARA_ERROR; + } + } + + if (OsCmdKeyCheck(cmdKey) != TRUE) { + return OS_ERRNO_SHELL_CMDREG_CMD_ERROR; + } + + (VOID)LOS_MuxPend(cmdInfo.muxLock, LOS_WAIT_FOREVER); + LOS_DL_LIST_FOR_EACH_ENTRY(cmdItemNode, &(cmdInfo.cmdList.list), CmdItemNode, list) { + if ((cmdType == cmdItemNode->cmd->cmdType) && + ((strlen(cmdKey) == strlen(cmdItemNode->cmd->cmdKey)) && + (strncmp((CHAR *)(cmdItemNode->cmd->cmdKey), cmdKey, strlen(cmdKey)) == 0))) { + (VOID)LOS_MuxPost(cmdInfo.muxLock); + return OS_ERRNO_SHELL_CMDREG_CMD_EXIST; + } + } + (VOID)LOS_MuxPost(cmdInfo.muxLock); + + return OsCmdItemCreate(cmdType, cmdKey, paraNum, cmdProc); +} + diff --git a/components/shell/src/base/shcmdparse.c b/components/shell/src/base/shcmdparse.c new file mode 100755 index 00000000..974f0ac9 --- /dev/null +++ b/components/shell/src/base/shcmdparse.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "shcmd.h" +#include "los_memory.h" + + +/* + * Filter out double quote or single-quoted strings at both ends + */ +LITE_OS_SEC_TEXT_MINOR CHAR *OsCmdParseStrdup(const CHAR *str) +{ + CHAR *tempStr = NULL; + CHAR *newStr = NULL; + + newStr = (CHAR *)LOS_MemAlloc(m_aucSysMem0, strlen(str) + 1); + if (newStr == NULL) { + return NULL; + } + + tempStr = newStr; + for (; *str != '\0'; str++) { + if ((*str == '\"') || (*str == '\'')) { + continue; + } + *newStr = *str; + newStr++; + } + *newStr = '\0'; + return tempStr; +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdParseParaGet(CHAR **value, const CHAR *paraTokenStr) +{ + if ((paraTokenStr == NULL) || (value == NULL)) { + return (UINT32)OS_ERROR; + } + + *value = OsCmdParseStrdup(paraTokenStr); + if (*value == NULL) { + return LOS_NOK; + } + return LOS_OK; +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdParseOneToken(CmdParsed *cmdParsed, UINT32 index, const CHAR *token) +{ + UINT32 ret = LOS_OK; + UINT32 tempLen; + + if (cmdParsed == NULL) { + return (UINT32)OS_ERROR; + } + + if (index == 0) { + if (cmdParsed->cmdType != CMD_TYPE_STD) { + return ret; + } + } + + if ((token != NULL) && (cmdParsed->paramCnt < CMD_MAX_PARAS)) { + tempLen = cmdParsed->paramCnt; + ret = OsCmdParseParaGet(&(cmdParsed->paramArray[tempLen]), token); + if (ret != LOS_OK) { + return ret; + } + cmdParsed->paramCnt++; + } + return ret; +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdTokenSplit(CHAR *cmdStr, CHAR split, CmdParsed *cmdParsed) +{ + enum { + STAT_INIT, + STAT_TOKEN_IN, + STAT_TOKEN_OUT + } state = STAT_INIT; + UINT32 count = 0; + CHAR *p = NULL; + CHAR *token = cmdStr; + UINT32 ret = LOS_OK; + BOOL quotes = FALSE; + + if (cmdStr == NULL) { + return (UINT32)OS_ERROR; + } + + for (p = cmdStr; (*p != '\0') && (ret == LOS_OK); p++) { + if (*p == '\"') { + SWITCH_QUOTES_STATUS(quotes); + } + switch (state) { + case STAT_INIT: + case STAT_TOKEN_IN: + if ((*p == split) && QUOTES_STATUS_CLOSE(quotes)) { + *p = '\0'; + ret = OsCmdParseOneToken(cmdParsed, count++, token); + state = STAT_TOKEN_OUT; + } + break; + case STAT_TOKEN_OUT: + if (*p != split) { + token = p; + state = STAT_TOKEN_IN; + } + break; + default: + break; + } + } + + if (((ret == LOS_OK) && (state == STAT_TOKEN_IN)) || (state == STAT_INIT)) { + ret = OsCmdParseOneToken(cmdParsed, count, token); + } + + return ret; +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsCmdParse(CHAR *cmdStr, CmdParsed *cmdParsed) +{ + if ((cmdStr == NULL) || (cmdParsed == NULL) || (strlen(cmdStr) == 0)) { + return (UINT32)OS_ERROR; + } + return OsCmdTokenSplit(cmdStr, ' ', cmdParsed); +} + diff --git a/components/shell/src/base/shmsg.c b/components/shell/src/base/shmsg.c new file mode 100755 index 00000000..9ae03dfc --- /dev/null +++ b/components/shell/src/base/shmsg.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "shmsg.h" +#include "shcmd.h" +#include "show.h" +#include "securec.h" + +UINT32 ShellMsgTypeGet(CmdParsed *cmdParsed, const CHAR *cmdType) +{ + CmdItemNode *curCmdItem = (CmdItemNode *)NULL; + UINT32 len; + UINT32 minLen; + CmdModInfo *cmdInfo = OsCmdInfoGet(); + + if ((cmdParsed == NULL) || (cmdType == NULL)) { + return OS_INVALID; + } + + len = strlen(cmdType); + LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(cmdInfo->cmdList.list), CmdItemNode, list) { + if ((len == strlen(curCmdItem->cmd->cmdKey)) && + (strncmp((CHAR *)(curCmdItem->cmd->cmdKey), cmdType, len) == 0)) { + minLen = (len < CMD_KEY_LEN) ? len : CMD_KEY_LEN; + (VOID)memcpy_s((CHAR *)(cmdParsed->cmdKeyword), CMD_KEY_LEN, cmdType, minLen); + cmdParsed->cmdType = curCmdItem->cmd->cmdType; + return LOS_OK; + } + } + + return OS_INVALID; +} + +char *GetCmdName(const char *cmdline, unsigned int len) +{ + unsigned int loop; + const char *tmpStr = NULL; + bool quotes = FALSE; + char *cmdName = NULL; + if (cmdline == NULL) { + return NULL; + } + + cmdName = (char *)malloc(len + 1); + if (cmdName == NULL) { + PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__); + return NULL; + } + + /* Scan the 'cmdline' string for command */ + /* Notice: Command string must not have any special name */ + for (tmpStr = cmdline, loop = 0; (*tmpStr != '\0') && (loop < len);) { + /* If reach a double quotes, switch the quotes matching status */ + if (*tmpStr == '\"') { + SWITCH_QUOTES_STATUS(quotes); + /* Ignore the double quote charactor itself */ + tmpStr++; + continue; + } + /* If detected a space which the quotes matching status is false */ + /* which said has detected the first space for seperator, finish this scan operation */ + if ((*tmpStr == ' ') && (QUOTES_STATUS_CLOSE(quotes))) { + break; + } + cmdName[loop] = *tmpStr++; + loop++; + } + cmdName[loop] = '\0'; + + return cmdName; +} + +int ShellCmdExec(const char *msgName, const char *cmdString) +{ + unsigned int uintRet; + errno_t err; + CmdParsed cmdParsed; + + if (msgName == NULL || cmdString == NULL) { + return -EFAULT; + } + err = memset_s(&cmdParsed, sizeof(CmdParsed), 0, sizeof(CmdParsed)); + if (err != EOK) { + return -EFAULT; + } + + uintRet = ShellMsgTypeGet(&cmdParsed, msgName); + + if (uintRet != LOS_OK) { + PRINTK("%s:command not found\n", msgName); + return -EFAULT; + } else { + + (void)OsCmdExec(&cmdParsed, (char *)cmdString); + } + return 0; +} + +unsigned int PreHandleCmdline(const char *input, char **output, unsigned int *outputlen) +{ + unsigned int shiftLen; + unsigned int ret; + const char *cmdBuf = input; + unsigned int cmdBufLen = strlen(cmdBuf); + char *shiftStr = (char *)malloc(cmdBufLen + 1); + + if (shiftStr == NULL) { + PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__); + return SH_NOK; + } + (void)memset_s(shiftStr, cmdBufLen + 1, 0, cmdBufLen + 1); + + /* Call function 'OsCmdKeyShift' to squeeze and clear useless or overmuch space if string buffer */ + ret = OsCmdKeyShift(cmdBuf, shiftStr, cmdBufLen + 1); + shiftLen = strlen(shiftStr); + if ((ret != SH_OK) || (shiftLen == 0)) { + ret = SH_NOK; + goto END_FREE_SHIFTSTR; + } + *output = shiftStr; + *outputlen = shiftLen; + + ret = SH_OK; + goto END; + +END_FREE_SHIFTSTR: + free(shiftStr); +END: + return ret; +} + +static void ParseAndExecCmdline(CmdParsed *cmdParsed, const char *cmdline, unsigned int len) +{ + int i; + unsigned int ret; + char *cmdlineOrigin = NULL; + char *cmdName = NULL; + + cmdlineOrigin = strdup(cmdline); + if (cmdlineOrigin == NULL) { + PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__); + return; + } + + cmdName = GetCmdName(cmdline, len); + if (cmdName == NULL) { + free(cmdlineOrigin); + PRINTK("malloc failure in %s[%d]\n", __FUNCTION__, __LINE__); + return; + } + + ret = OsCmdParse((char *)cmdline, cmdParsed); + if (ret != SH_OK) { + PRINTK("cmd parse failure in %s[%d]\n", __FUNCTION__, __LINE__); + goto OUT; + } + + (void)ShellCmdExec(cmdName, cmdlineOrigin); + +OUT: + for (i = 0; i < cmdParsed->paramCnt; i++) { + if (cmdParsed->paramArray[i] != NULL) { + free(cmdParsed->paramArray[i]); + cmdParsed->paramArray[i] = NULL; + } + } + free(cmdName); + free(cmdlineOrigin); +} + +LITE_OS_SEC_TEXT_MINOR void ExecCmdline(const char *cmdline) +{ + unsigned int ret; + char *output = NULL; + unsigned int outputlen; + CmdParsed cmdParsed; + + if (cmdline == NULL) { + return; + } + + OsShellInit(0); + + /* strip out unnecessary characters */ + ret = PreHandleCmdline(cmdline, &output, &outputlen); + if (ret == SH_NOK) { + return; + } + + (void)memset_s(&cmdParsed, sizeof(CmdParsed), 0, sizeof(CmdParsed)); + ParseAndExecCmdline(&cmdParsed, output, outputlen); + free(output); +} + diff --git a/components/shell/src/base/show.c b/components/shell/src/base/show.c new file mode 100755 index 00000000..b52bba13 --- /dev/null +++ b/components/shell/src/base/show.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "show.h" +#include "shmsg.h" +#include "shcmd.h" + + +STATIC BOOL g_shellSourceFlag = FALSE; + +STATIC UINT32 OsShellCmdInit(VOID) +{ + UINT32 ret = OsCmdInit(); + if (ret != LOS_OK) { + return ret; + } + + return OsShellSysCmdRegister(); +} + +UINT32 OsShellInit(INT32 consoleId) +{ + if (g_shellSourceFlag == FALSE) { + UINT32 ret = OsShellCmdInit(); + if (ret == LOS_OK) { + g_shellSourceFlag = TRUE; + } else { + return ret; + } + } + + return 0; +} + diff --git a/components/shell/src/cmds/date_shell.c b/components/shell/src/cmds/date_shell.c new file mode 100755 index 00000000..79135049 --- /dev/null +++ b/components/shell/src/cmds/date_shell.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "shcmd.h" +#include "shell.h" +#include "stdlib.h" +#include "sys/time.h" +#include "los_typedef.h" +#include "sys/stat.h" +#include "securec.h" + +#define DATE_ERR (-1) +#define DATE_OK 0 + +INT32 OsShellCmdDate(INT32 argc, const CHAR **argv) +{ + struct timeval nowTime; + + if (argc == 1) { /* 1:count of parameters */ + if (gettimeofday(&nowTime, NULL)) { + return DATE_ERR; + } + PRINTK("%s\n", ctime(&nowTime.tv_sec)); + return DATE_OK; + } + + return DATE_OK; +} + diff --git a/components/shell/src/cmds/fullpath.c b/components/shell/src/cmds/fullpath.c new file mode 100755 index 00000000..7981c2e2 --- /dev/null +++ b/components/shell/src/cmds/fullpath.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "errno.h" +#include "limits.h" +#include "shell.h" +#include "show.h" + +#define TEMP_PATH_MAX (PATH_MAX + SHOW_MAX_LEN) + +static unsigned int VfsStrnlen(const char *str, size_t maxlen) +{ + const char *p = NULL; + + for (p = str; ((maxlen-- != 0) && (*p != '\0')); ++p) {} + + return p - str; +} + +/* abandon the redundant '/' in the path, only keep one. */ +static char *StrPath(char *path) +{ + char *dest = path; + char *src = path; + + while (*src != '\0') { + if (*src == '/') { + *dest++ = *src++; + while (*src == '/') { + src++; + } + continue; + } + *dest++ = *src++; + } + *dest = '\0'; + return path; +} + +static void StrRemovePathEndSlash(char *dest, const char *fullpath) +{ + if ((*dest == '.') && (*(dest - 1) == '/')) { + *dest = '\0'; + dest--; + } + if ((dest != fullpath) && (*dest == '/')) { + *dest = '\0'; + } +} + +static char *StrNormalizePath(char *fullpath) +{ + char *dest = fullpath; + char *src = fullpath; + + /* 2: The position of the path character: / and the end character /0 */ + + while (*src != '\0') { + if (*src == '.') { + if (*(src + 1) == '/') { + src += 2; + continue; + } else if (*(src + 1) == '.') { + if ((*(src + 2) == '/') || (*(src + 2) == '\0')) { + src += 2; + } else { + while ((*src != '\0') && (*src != '/')) { + *dest++ = *src++; + } + continue; + } + } else { + *dest++ = *src++; + continue; + } + } else { + *dest++ = *src++; + continue; + } + + if ((dest - 1) != fullpath) { + dest--; + } + + while ((dest > fullpath) && (*(dest - 1) != '/')) { + dest--; + } + + if (*src == '/') { + src++; + } + } + + *dest = '\0'; + + /* remove '/' in the end of path if exist */ + + dest--; + + StrRemovePathEndSlash(dest, fullpath); + return dest; +} + +static int VfsNormalizePathParameCheck(const char *filename, char **pathname) +{ + int namelen; + char *name = NULL; + + if (pathname == NULL) { + return -EINVAL; + } + + /* check parameters */ + + if (filename == NULL) { + *pathname = NULL; + return -EINVAL; + } + + namelen = VfsStrnlen(filename, PATH_MAX); + if (!namelen) { + *pathname = NULL; + return -EINVAL; + } else if (namelen >= PATH_MAX) { + *pathname = NULL; + return -ENAMETOOLONG; + } + + for (name = (char *)filename + namelen; ((name != filename) && (*name != '/')); name--) { + if (strlen(name) > NAME_MAX) { + *pathname = NULL; + return -ENAMETOOLONG; + } + } + + return namelen; +} + +static char *VfsNotAbsolutePath(const char *directory, const char *filename, char **pathname, int namelen) +{ + int ret; + char *fullpath = NULL; + + /* 2: The position of the path character: / and the end character /0 */ + + if ((namelen > 1) && (filename[0] == '.') && (filename[1] == '/')) { + filename += 2; + } + + fullpath = (char *)malloc(strlen(directory) + namelen + 2); + if (fullpath == NULL) { + *pathname = NULL; + SetErrno(ENOMEM); + return (char *)NULL; + } + + /* join path and file name */ + + ret = snprintf_s(fullpath, strlen(directory) + namelen + 2, strlen(directory) + namelen + 1, + "%s/%s", directory, filename); + if (ret < 0) { + *pathname = NULL; + free(fullpath); + SetErrno(ENAMETOOLONG); + return (char *)NULL; + } + + return fullpath; +} + +static char *VfsNormalizeFullpath(const char *directory, const char *filename, char **pathname, int namelen) +{ + char *fullpath = NULL; + + if (filename[0] != '/') { + /* not a absolute path */ + + fullpath = VfsNotAbsolutePath(directory, filename, pathname, namelen); + if (fullpath == NULL) { + return (char *)NULL; + } + } else { + /* it's a absolute path, use it directly */ + + fullpath = strdup(filename); /* copy string */ + + if (fullpath == NULL) { + *pathname = NULL; + SetErrno(ENOMEM); + return (char *)NULL; + } + if (filename[1] == '/') { + *pathname = NULL; + free(fullpath); + SetErrno(EINVAL); + return (char *)NULL; + } + } + + return fullpath; +} + +int VfsNormalizePath(const char *directory, const char *filename, char **pathname) +{ + char *fullpath = NULL; + int namelen; + + namelen = VfsNormalizePathParameCheck(filename, pathname); + if (namelen < 0) { + return namelen; + } + + if ((directory == NULL) && (filename[0] != '/')) { + PRINT_ERR("NO_WORKING_DIR\n"); + *pathname = NULL; + return -EINVAL; + } + + /* 2: The position of the path character: / and the end character /0 */ + + if ((filename[0] != '/') && (strlen(directory) + namelen + 2 > TEMP_PATH_MAX)) { + return -ENAMETOOLONG; + } + + fullpath = VfsNormalizeFullpath(directory, filename, pathname, namelen); + if (fullpath == NULL) { + return -errno; + } + + (void)StrPath(fullpath); + (void)StrNormalizePath(fullpath); + if (strlen(fullpath) >= PATH_MAX) { + *pathname = NULL; + free(fullpath); + return -ENAMETOOLONG; + } + + *pathname = fullpath; + return ENOERR; +} + diff --git a/components/shell/src/cmds/mempt_shellcmd.c b/components/shell/src/cmds/mempt_shellcmd.c new file mode 100755 index 00000000..40b66d9c --- /dev/null +++ b/components/shell/src/cmds/mempt_shellcmd.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdlib.h" +#include "shcmd.h" +#include "shell.h" + +#define MEM_SIZE_1K 0x400 +#define MEM_SIZE_1M 0x100000 + +#define MEM_SIZE_TO_KB(size) (((size) + (MEM_SIZE_1K >> 1)) / MEM_SIZE_1K) +#define MEM_SIZE_TO_MB(size) (((size) + (MEM_SIZE_1M >> 1)) / MEM_SIZE_1M) + +LITE_OS_SEC_TEXT_MINOR STATIC UINT32 OsShellCmdFreeInfo(INT32 argc, const CHAR *argv[]) +{ + UINT32 memUsed = LOS_MemTotalUsedGet(m_aucSysMem0); + UINT32 totalMem = LOS_MemPoolSizeGet(m_aucSysMem0); + UINT32 freeMem = totalMem - memUsed; + + if ((argc == 0) || + ((argc == 1) && (strcmp(argv[0], "-k") == 0)) || + ((argc == 1) && (strcmp(argv[0], "-m") == 0))) { + PRINTK("\r\n total used free\n"); + } + + if ((argc == 1) && (strcmp(argv[0], "-k") == 0)) { + PRINTK("Mem: %-9u %-10u %-10u\n", MEM_SIZE_TO_KB(totalMem), MEM_SIZE_TO_KB(memUsed), + MEM_SIZE_TO_KB(freeMem)); + } else if ((argc == 1) && (strcmp(argv[0], "-m") == 0)) { + PRINTK("Mem: %-9u %-10u %-10u\n", MEM_SIZE_TO_MB(totalMem), MEM_SIZE_TO_MB(memUsed), + MEM_SIZE_TO_MB(freeMem)); + } else if (argc == 0) { + PRINTK("Mem: %-9u %-10u %-10u\n", totalMem, memUsed, freeMem); + } else { + PRINTK("\nUsage: free or free [-k/-m]\n"); + return OS_ERROR; + } + return 0; +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdFree(INT32 argc, const CHAR *argv[]) +{ + if (argc > 1) { + PRINTK("\nUsage: free or free [-k/-m]\n"); + return OS_ERROR; + } + if (OsShellCmdFreeInfo(argc, argv) != 0) { + return OS_ERROR; + } + return 0; +} + diff --git a/components/shell/src/cmds/shell_shellcmd.c b/components/shell/src/cmds/shell_shellcmd.c new file mode 100755 index 00000000..fd7cd309 --- /dev/null +++ b/components/shell/src/cmds/shell_shellcmd.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "shcmd.h" + +INT32 OsShellCmdHelp(INT32 argc, const CHAR **argv) +{ + UINT32 loop = 0; + CmdItemNode *curCmdItem = NULL; + CmdModInfo *cmdInfo = OsCmdInfoGet(); + + (VOID)argv; + if (argc > 0) { + PRINTK("\nUsage: help\n"); + return OS_ERROR; + } + + PRINTK("*******************shell commands:*************************\n"); + LOS_DL_LIST_FOR_EACH_ENTRY(curCmdItem, &(cmdInfo->cmdList.list), CmdItemNode, list) { + if ((loop & (8 - 1)) == 0) { /* 8 - 1:just align print */ + PRINTK("\n"); + } + PRINTK("%-12s ", curCmdItem->cmd->cmdKey); + + loop++; + } + + PRINTK("\n"); + return 0; +} diff --git a/components/shell/src/cmds/task_shellcmd.c b/components/shell/src/cmds/task_shellcmd.c new file mode 100755 index 00000000..aa56f2c2 --- /dev/null +++ b/components/shell/src/cmds/task_shellcmd.c @@ -0,0 +1,123 @@ +#include "stdlib.h" +#include "los_config.h" +#include "los_exc.h" +#include "los_task.h" +#include "los_sem.h" +#include "shcmd.h" +#include "shell.h" + +#define OS_INVALID_SEM_ID 0xFFFFFFFF + +LITE_OS_SEC_TEXT_MINOR UINT8 *OsShellCmdConvertTskStatus(UINT16 taskStatus) +{ + if (taskStatus & OS_TASK_STATUS_RUNNING) { + return (UINT8 *)"Running"; + } else if (taskStatus & OS_TASK_STATUS_READY) { + return (UINT8 *)"Ready"; + } else { + if (taskStatus & OS_TASK_STATUS_DELAY) { + return (UINT8 *)"Delay"; + } else if (taskStatus & OS_TASK_STATUS_PEND_QUEUE) { + return (UINT8 *)"Pend"; + } else if (taskStatus & OS_TASK_STATUS_PEND) { + return (UINT8 *)"Pend"; + } else if (taskStatus & OS_TASK_STATUS_SUSPEND) { + return (UINT8 *)"Suspend"; + } + } + + return (UINT8 *)"Invalid"; +} + +LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoTitle(VOID) +{ + PRINTK("\r\nName TaskEntryAddr TID "); + + PRINTK("Priority Status " + "StackSize StackPoint TopOfStack"); + + PRINTK("\n"); + PRINTK("---- ------------- --- "); + PRINTK("-------- -------- " + "--------- ---------- ----------"); + PRINTK("\n"); +} + +LITE_OS_SEC_TEXT_MINOR STATIC INLINE UINT32 OsGetSemID(const LosTaskCB *taskCB) +{ + UINT32 semId = OS_INVALID_SEM_ID; + + if (taskCB->taskSem != NULL) { + semId = ((LosSemCB *)taskCB->taskSem)->semID; + } + + return semId; +} + +LITE_OS_SEC_TEXT_MINOR STATIC VOID OsShellCmdTskInfoData(const LosTaskCB *allTaskArray) +{ + const LosTaskCB *taskCB = NULL; + UINT32 loop; + UINT32 semId; + + for (loop = 0; loop < g_taskMaxNum; ++loop) { + taskCB = allTaskArray + loop; + if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { + continue; + } + + semId = OsGetSemID(taskCB); + + PRINTK("%-23s%-20p0x%-5x", taskCB->taskName, taskCB->taskEntry, taskCB->taskID); + PRINTK("%-11u%-13s0x%-11x 0x%-8x 0x%-10x ", taskCB->priority, + OsShellCmdConvertTskStatus(taskCB->taskStatus), taskCB->stackSize, + taskCB->stackPointer, taskCB->topOfStack, semId); + PRINTK("\n"); + } +} + +LITE_OS_SEC_TEXT_MINOR UINT32 OsShellCmdTskInfoGet(UINT32 taskId) +{ + BOOL backupFlag = TRUE; + UINT32 size; + LosTaskCB *tcbArray = NULL; + INT32 ret; + + if (taskId == OS_ALL_TASK_MASK) { + size = g_taskMaxNum * sizeof(LosTaskCB); + tcbArray = (LosTaskCB *)LOS_MemAlloc(m_aucSysMem0, size); + if (tcbArray == NULL) { + PRINTK("Memory is not enough to save task info!\n"); + tcbArray = g_taskCBArray; + backupFlag = FALSE; + } + if (backupFlag == TRUE) { + ret = memcpy_s(tcbArray, size, g_taskCBArray, size); + if (ret != 0) { + return LOS_NOK; + } + } + + OsShellCmdTskInfoTitle(); + OsShellCmdTskInfoData(tcbArray); + + if (backupFlag == TRUE) { + (VOID)LOS_MemFree(m_aucSysMem0, tcbArray); + } + } + + return LOS_OK; +} + +INT32 OsShellCmdDumpTask(INT32 argc, const CHAR **argv) +{ + size_t taskId = OS_ALL_TASK_MASK; + + if (argc < 1) { + return OsShellCmdTskInfoGet((UINT32)taskId); + } else { + PRINTK("\nUsage: task\n"); + return OS_ERROR; + } +} + diff --git a/components/shell/src/cmds/vfs_shellcmd.c b/components/shell/src/cmds/vfs_shellcmd.c new file mode 100755 index 00000000..a9be1791 --- /dev/null +++ b/components/shell/src/cmds/vfs_shellcmd.c @@ -0,0 +1,956 @@ +/* + * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "los_config.h" +#include "sys/mount.h" + +#include "los_task.h" +#include "los_typedef.h" +#include "shell.h" +#include "sys/stat.h" +#include "stdlib.h" +#include "unistd.h" +#include "fcntl.h" +#include "sys/statfs.h" +#include "stdio.h" +#include "pthread.h" + +#include "shcmd.h" +#include "securec.h" +#include "show.h" + +#include +#include + +#define VFS_ERROR OS_ERROR +#define SHOW_MAX_LEN CMD_MAX_LEN +#define TEMP_PATH_MAX (PATH_MAX + SHOW_MAX_LEN) + +typedef enum { + RM_RECURSIVER, + RM_FILE, + RM_DIR, + CP_FILE, + CP_COUNT +} wildcard_type; + +#define ERROR_OUT_IF(condition, message_function, handler) \ + do { \ + if (condition) { \ + message_function; \ + handler; \ + } \ + } while (0) + +int OsShellCmdDoChdir(const char *path) +{ + char *fullpath = NULL; + char *fullpathBak = NULL; + DIR *dirent = NULL; + int ret; + char *shellWorkingDirectory = OsShellGetWorkingDirtectory(); + if (shellWorkingDirectory == NULL) { + return -1; + } + + if (path == NULL) { + LOS_TaskLock(); + PRINTK("%s\n", shellWorkingDirectory); + LOS_TaskUnlock(); + return 0; + } + + ERROR_OUT_IF(strlen(path) > PATH_MAX, SetErr(ENOTDIR, "cd error"), return -1); + + ret = VfsNormalizePath(shellWorkingDirectory, path, &fullpath); + ERROR_OUT_IF(ret < 0, SetErr(-ret, "cd error"), return -1); + + fullpathBak = fullpath; + dirent = opendir(fullpath); + if (dirent == NULL) { + free(fullpathBak); + /* this is a not exist directory */ + PRINTK("no such file or directory\n"); + return -1; + } + + /* close directory stream */ + (void)closedir(dirent); + + /* copy full path to working directory */ + LOS_TaskLock(); + ret = strncpy_s(shellWorkingDirectory, PATH_MAX, fullpath, strlen(fullpath)); + if (ret != EOK) { + free(fullpathBak); + LOS_TaskUnlock(); + return -1; + } + LOS_TaskUnlock(); + /* release normalize directory path name */ + + free(fullpathBak); + return 0; +} + +static char *OsLsGetFullpath(const char *path, struct dirent *pdirent) +{ + char *fullpath = NULL; + int ret; + + if (path[1] != '\0') { + fullpath = (char *)malloc(strlen(path) + strlen(pdirent->d_name) + 2); + if (fullpath == NULL) { + goto exit_with_nomem; + } + + ret = snprintf_s(fullpath, strlen(path) + strlen(pdirent->d_name) + 2, + strlen(path) + strlen(pdirent->d_name) + 1, "%s/%s", path, pdirent->d_name); + if (ret < 0) { + free(fullpath); + return NULL; + } + } else { + fullpath = (char *)malloc(strlen(pdirent->d_name) + 2); + if (fullpath == NULL) { + goto exit_with_nomem; + } + + ret = snprintf_s(fullpath, strlen(pdirent->d_name) + 2, strlen(pdirent->d_name) + 1, + "/%s", pdirent->d_name); + if (ret < 0) { + free(fullpath); + return NULL; + } + } +return fullpath; +exit_with_nomem: + return (char *)NULL; +} + +void OsLs(const char *pathname) +{ + struct dirent *pdirent = NULL; + char *path = NULL; + char *fullpath = NULL; + char *fullpathBak = NULL; + int ret; + struct stat statInfo = { 0 }; + DIR *d = NULL; + + /* list all directory and file */ + if (pathname == NULL) { + path = strdup("/"); + if (path == NULL) { + return; + } + } else { + ret = VfsNormalizePath(NULL, pathname, &path); + if (ret < 0) { + SetErrno(-ret); + return; + } + } + + d = opendir(path); + if (d == NULL) { + PRINT_ERR("No such directory = %s\n", path); + } else { + PRINTK("Directory %s:\n", path); + do { + pdirent = readdir(d); + if (pdirent != NULL) { + (void)memset_s(&statInfo, sizeof(struct stat), 0, sizeof(struct stat)); + fullpath = OsLsGetFullpath(path, pdirent); + if (fullpath == NULL) { + free(path); + (void)closedir(d); + return; + } + + fullpathBak = fullpath; + if (stat(fullpath, &statInfo) == 0) { + PRINTK("%-20s", pdirent->d_name); + if (S_ISDIR(statInfo.st_mode)) { + PRINTK(" %-25s\n", ""); + } else { + PRINTK(" %-25lu\n", statInfo.st_size); + } + } else { + PRINTK("BAD file: %s\n", pdirent->d_name); + } + free(fullpathBak); + } + } while (pdirent != NULL); + + (void)closedir(d); + } +} + +int OsShellCmdLs(int argc, const char **argv) +{ + char *fullpath = NULL; + const char *filename = NULL; + int ret; + char *shellWorkingDirectory = OsShellGetWorkingDirtectory(); + if (shellWorkingDirectory == NULL) { + return -1; + } + + ERROR_OUT_IF(argc > 1, PRINTK("ls or ls [DIRECTORY]\n"), return -1); + + if (argc == 0) { + OsLs(shellWorkingDirectory); + return 0; + } + + filename = argv[0]; + ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath); + ERROR_OUT_IF(ret < 0, SetErr(-ret, "ls error"), return -1); + + OsLs(fullpath); + free(fullpath); + + return 0; +} + +int OsShellCmdCd(int argc, const char **argv) +{ + if (argc == 0) { + (void)OsShellCmdDoChdir("/"); + return 0; + } + + OsShellCmdDoChdir(argv[0]); + return 0; +} + +#define CAT_BUF_SIZE 512 +#define CAT_TASK_PRIORITY 10 +#define CAT_TASK_STACK_SIZE 0x3000 +pthread_mutex_t g_mutex_cat = PTHREAD_MUTEX_INITIALIZER; + +int OsShellCmdCat(int argc, const char **argv) +{ + char *fullpath = NULL; + int ret; + CHAR buf[CAT_BUF_SIZE]; + size_t size; + + char *shellWorkingDirectory = OsShellGetWorkingDirtectory(); + + if (shellWorkingDirectory == NULL) { + return -1; + } + + ERROR_OUT_IF(argc != 1, PRINTK("cat [FILE]\n"), return -1); + + ret = VfsNormalizePath(shellWorkingDirectory, argv[0], &fullpath); + ERROR_OUT_IF(ret < 0, SetErr(-ret, "cat error"), return -1); + + int fd = open(fullpath, O_RDONLY, 0666); + + if (fd == -1) { + ret = -1; + return ret; + } + + do { + (void)memset_s(buf, sizeof(buf), 0, CAT_BUF_SIZE); + size = read(fd, buf, CAT_BUF_SIZE - 1); + if ((int)size < 0) { + free(fullpath); + close(fd); + return -1; + } + PRINTK("%s", buf); + (void)LOS_TaskDelay(1); + } while (size == CAT_BUF_SIZE); + + free(fullpath); + close(fd); + + return ret; +} + +int OsShellCmdMkdir(int argc, const char **argv) +{ + int ret; + char *fullpath = NULL; + const char *filename = NULL; + char *shellWorkingDirectory = OsShellGetWorkingDirtectory(); + if (shellWorkingDirectory == NULL) { + return -1; + } + + ERROR_OUT_IF(argc != 1, PRINTK("mkdir [DIRECTORY]\n"), return 0); + + filename = argv[0]; + ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath); + ERROR_OUT_IF(ret < 0, SetErr(-ret, "mkdir error"), return -1); + + ret = mkdir(fullpath, S_IRWXU | S_IRWXG | S_IRWXO); + if (ret == -1) { + perror("mkdir error"); + } + free(fullpath); + return 0; +} + +int OsShellCmdPwd(int argc, const char **argv) +{ + char buf[SHOW_MAX_LEN] = {0}; + DIR *dir = NULL; + char *shellWorkingDirectory = OsShellGetWorkingDirtectory(); + if (shellWorkingDirectory == NULL) { + return -1; + } + + ERROR_OUT_IF(argc > 0, PRINTK("\nUsage: pwd\n"), return -1); + + LOS_TaskLock(); + if (strncpy_s(buf, SHOW_MAX_LEN, shellWorkingDirectory, SHOW_MAX_LEN - 1) != EOK) { + LOS_TaskUnlock(); + PRINTK("pwd error: strncpy_s error!\n"); + return -1; + } + LOS_TaskUnlock(); + + PRINTK("%s\n", buf); + return 0; +} + +int OsShellCmdTouch(int argc, const char **argv) +{ + int ret; + int fd = -1; + char *fullpath = NULL; + const char *filename = NULL; + char *shellWorkingDirectory = OsShellGetWorkingDirtectory(); + if (shellWorkingDirectory == NULL) { + return -1; + } + + ERROR_OUT_IF(argc != 1, PRINTK("touch [FILE]\n"), return -1); + + filename = argv[0]; + ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath); + ERROR_OUT_IF(ret < 0, SetErr(-ret, "touch error"), return -1); + + fd = open(fullpath, O_RDWR | O_CREAT, 0777); + free(fullpath); + if (fd == -1) { + perror("touch error"); + return -1; + } + + (void)close(fd); + return 0; +} + +#define CP_BUF_SIZE 4096 +pthread_mutex_t g_mutexCp = PTHREAD_MUTEX_INITIALIZER; + +static int OsShellCmdDoCp(const char *srcFilePath, const char *dstFileName) +{ + int ret; + char *srcFullPath = NULL; + char *drcFullPath = NULL; + const char *srcFileName = NULL; + char *dstFilePath = NULL; + char *buf = NULL; + const char *filename = NULL; + size_t rdSize, wrSize; + int srcFd = -1; + int dstFd = -1; + struct stat statBuf; + mode_t srcMode; + char *shellWorkingDirectory = OsShellGetWorkingDirtectory(); + if (shellWorkingDirectory == NULL) { + return -1; + } + + buf = (char *)malloc(CP_BUF_SIZE); + if (buf == NULL) { + PRINTK("cp error: Out of memory!\n"); + return -1; + } + + /* Get source fullpath. */ + ret = VfsNormalizePath(shellWorkingDirectory, srcFilePath, &srcFullPath); + if (ret < 0) { + SetErrno(-ret); + PRINTK("cp error: %s\n", strerror(errno)); + free(buf); + return -1; + } + + /* Is source path exist? */ + ret = stat(srcFullPath, &statBuf); + if (ret == -1) { + PRINTK("cp %s error: %s\n", srcFullPath, strerror(errno)); + goto errout_with_srcpath; + } + srcMode = statBuf.st_mode; + /* Is source path a directory? */ + if (S_ISDIR(statBuf.st_mode)) { + PRINTK("cp %s error: Source file can't be a directory.\n", srcFullPath); + goto errout_with_srcpath; + } + + /* Get dest fullpath. */ + drcFullPath = strdup(dstFileName); + if (drcFullPath == NULL) { + PRINTK("cp error: Out of memory.\n"); + goto errout_with_srcpath; + } + /* Is dest path exist? */ + ret = stat(drcFullPath, &statBuf); + if (ret == 0) { + /* Is dest path a directory? */ + if (S_ISDIR(statBuf.st_mode)) { + /* Get source file name without '/'. */ + srcFileName = srcFilePath; + while (1) { + filename = strchr(srcFileName, '/'); + if (filename == NULL) { + break; + } + srcFileName = filename + 1; + } + /* Add the source file after dest path. */ + ret = VfsNormalizePath(drcFullPath, srcFileName, &dstFilePath); + if (ret < 0) { + SetErrno(-ret); + PRINTK("cp error. %s.\n", strerror(errno)); + goto errout_with_path; + } + free(drcFullPath); + drcFullPath = dstFilePath; + } + } + + /* Is dest file same as source file? */ + if (strcmp(srcFullPath, drcFullPath) == 0) { + PRINTK("cp error: '%s' and '%s' are the same file\n", srcFullPath, drcFullPath); + goto errout_with_path; + } + + /* Copy begins. */ + (void)pthread_mutex_lock(&g_mutexCp); + srcFd = open(srcFullPath, O_RDONLY); + if (srcFd < 0) { + PRINTK("cp error: can't open %s. %s.\n", srcFullPath, strerror(errno)); + goto errout_with_mutex; + } + + dstFd = open(drcFullPath, O_CREAT | O_WRONLY | O_TRUNC, srcMode); + if (dstFd < 0) { + PRINTK("cp error: can't create %s. %s.\n", drcFullPath, strerror(errno)); + goto errout_with_srcfd; + } + + do { + (void)memset_s(buf, CP_BUF_SIZE, 0, CP_BUF_SIZE); + rdSize = read(srcFd, buf, CP_BUF_SIZE); + if (rdSize < 0) { + PRINTK("cp %s %s failed. %s.\n", srcFullPath, drcFullPath, strerror(errno)); + goto errout_with_fd; + } + wrSize = write(dstFd, buf, rdSize); + if (wrSize != rdSize) { + PRINTK("cp %s %s failed. %s.\n", srcFullPath, drcFullPath, strerror(errno)); + goto errout_with_fd; + } + } while (rdSize == CP_BUF_SIZE); + + /* Release resource. */ + free(buf); + free(srcFullPath); + free(drcFullPath); + (void)close(srcFd); + (void)close(dstFd); + (void)pthread_mutex_unlock(&g_mutexCp); + return LOS_OK; + +errout_with_fd: + (void)close(dstFd); +errout_with_srcfd: + (void)close(srcFd); +errout_with_mutex: + (void)pthread_mutex_unlock(&g_mutexCp); +errout_with_path: + free(drcFullPath); +errout_with_srcpath: + free(srcFullPath); + free(buf); + return -1; +} + +/* The separator and EOF for a directory fullpath: '/'and '\0' */ +#define SEPARATOR_EOF_LEN 2 + +static int OsShellCmdDoRmdir(const char *pathname) +{ + struct dirent *dirent = NULL; + struct stat statInfo; + DIR *d = NULL; + char *fullpath = NULL; + int ret; + + (void)memset_s(&statInfo, sizeof(statInfo), 0, sizeof(struct stat)); + if (stat(pathname, &statInfo) != 0) { + return -1; + } + + if (S_ISREG(statInfo.st_mode) || S_ISLNK(statInfo.st_mode)) { + return remove(pathname); + } + d = opendir(pathname); + if (d == NULL) { + return -1; + } + while (1) { + dirent = readdir(d); + if (dirent == NULL) { + break; + } + if (strcmp(dirent->d_name, "..") && strcmp(dirent->d_name, ".")) { + size_t fullPathBufSize = strlen(pathname) + strlen(dirent->d_name) + SEPARATOR_EOF_LEN; + if (fullPathBufSize <= 0) { + PRINTK("buffer size is invalid!\n"); + (void)closedir(d); + return -1; + } + fullpath = (char *)malloc(fullPathBufSize); + if (fullpath == NULL) { + PRINTK("malloc failure!\n"); + (void)closedir(d); + return -1; + } + ret = snprintf_s(fullpath, fullPathBufSize, fullPathBufSize - 1, "%s/%s", pathname, dirent->d_name); + if (ret < 0) { + PRINTK("name is too long!\n"); + free(fullpath); + (void)closedir(d); + return -1; + } + (void)OsShellCmdDoRmdir(fullpath); + free(fullpath); + } + } + (void)closedir(d); + return rmdir(pathname); +} + +/* Wildcard matching operations */ +static int OsWildcardMatch(const char *src, const char *filename) +{ + int ret; + + if (*src != '\0') { + if (*filename == '*') { + while ((*filename == '*') || (*filename == '?')) { + filename++; + } + + if (*filename == '\0') { + return 0; + } + + while (*src != '\0' && !(*src == *filename)) { + src++; + } + + if (*src == '\0') { + return -1; + } + + ret = OsWildcardMatch(src, filename); + + while ((ret != 0) && (*(++src) != '\0')) { + if (*src == *filename) { + ret = OsWildcardMatch(src, filename); + } + } + return ret; + } else { + if ((*src == *filename) || (*filename == '?')) { + return OsWildcardMatch(++src, ++filename); + } + return -1; + } + } + + while (*filename != '\0') { + if (*filename != '*') { + return -1; + } + filename++; + } + return 0; +} + +/* To determine whether a wildcard character exists in a path */ +static int OsIsContainersWildcard(const char *filename) +{ + while (*filename != '\0') { + if ((*filename == '*') || (*filename == '?')) { + return 1; + } + filename++; + } + return 0; +} + +/* Delete a matching file or directory */ + +static int OsWildcardDeleteFileOrDir(const char *fullpath, wildcard_type mark) +{ + int ret; + + switch (mark) { + case RM_RECURSIVER: + ret = OsShellCmdDoRmdir(fullpath); + break; + case RM_FILE: + ret = unlink(fullpath); + break; + case RM_DIR: + ret = rmdir(fullpath); + break; + default: + return VFS_ERROR; + } + if (ret == -1) { + PRINTK("%s ", fullpath); + perror("rm/rmdir error!"); + return ret; + } + + PRINTK("%s match successful!delete!\n", fullpath); + return 0; +} + +/* Split the path with wildcard characters */ + +static char* OsWildcardSplitPath(char *fullpath, char **handle, char **wait) +{ + int n; + int a = 0; + int b = 0; + int len = strlen(fullpath); + + for (n = 0; n < len; n++) { + if (fullpath[n] == '/') { + if (b != 0) { + fullpath[n] = '\0'; + *wait = fullpath + n + 1; + break; + } + a = n; + } else if (fullpath[n] == '*' || fullpath[n] == '?') { + b = n; + fullpath[a] = '\0'; + if (a == 0) { + *handle = fullpath + a + 1; + continue; + } + *handle = fullpath + a + 1; + } + } + return fullpath; +} + +/* Handling entry of the path with wildcard characters */ + +static int OsWildcardExtractDirectory(char *fullpath, void *dst, wildcard_type mark) +{ + char separator[] = "/"; + char src[PATH_MAX] = {0}; + struct dirent *dirent = NULL; + char *f = NULL; + char *s = NULL; + char *t = NULL; + int ret = 0; + DIR *d = NULL; + struct stat statBuf; + int deleteFlag = 0; + + f = OsWildcardSplitPath(fullpath, &s, &t); + + if (s == NULL) { + if (mark == CP_FILE) { + ret = OsShellCmdDoCp(fullpath, dst); + } else if (mark == CP_COUNT) { + ret = stat(fullpath, &statBuf); + if (ret == 0 && (S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode))) { + (*(int *)dst)++; + } + } else { + ret = OsWildcardDeleteFileOrDir(fullpath, mark); + } + return ret; + } + + d = (*f == '\0') ? opendir("/") : opendir(f); + + if (d == NULL) { + perror("opendir error"); + return VFS_ERROR; + } + + while (1) { + dirent = readdir(d); + if (dirent == NULL) { + break; + } + + ret = strcpy_s(src, PATH_MAX, f); + if (ret != EOK) { + goto closedir_out; + } + + ret = OsWildcardMatch(dirent->d_name, s); + if (ret == 0) { + ret = strcat_s(src, sizeof(src), separator); + if (ret != EOK) { + goto closedir_out; + } + ret = strcat_s(src, sizeof(src), dirent->d_name); + if (ret != EOK) { + goto closedir_out; + } + if (t == NULL) { + if (mark == CP_FILE) { + ret = OsShellCmdDoCp(src, dst); + } else if (mark == CP_COUNT) { + ret = stat(src, &statBuf); + if (ret == 0 && (S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode))) { + (*(int *)dst)++; + if ((*(int *)dst) > 1) { + break; + } + } + } else { + ret = OsWildcardDeleteFileOrDir(src, mark); + if (ret == 0) { + deleteFlag = 1; + } + } + } else { + ret = strcat_s(src, sizeof(src), separator); + if (ret != EOK) { + goto closedir_out; + } + ret = strcat_s(src, sizeof(src), t); + if (ret != EOK) { + goto closedir_out; + } + ret = OsWildcardExtractDirectory(src, dst, mark); + if (mark == CP_COUNT && (*(int *)dst) > 1) { + break; + } + } + } + } + (void)closedir(d); + if (deleteFlag == 1) { + ret = 0; + } + return ret; +closedir_out: + (void)closedir(d); + return VFS_ERROR; +} + +int OsShellCmdCp(int argc, const char **argv) +{ + int ret; + const char *src = NULL; + const char *dst = NULL; + char *srcFullPath = NULL; + char *drcFullPath = NULL; + struct stat statBuf; + int count = 0; + char *shellWorkingDirectory = OsShellGetWorkingDirtectory(); + if (shellWorkingDirectory == NULL) { + return -1; + } + + ERROR_OUT_IF(argc < 2, PRINTK("cp [SOURCEFILE] [DESTFILE]\n"), return -1); + + src = argv[0]; + dst = argv[1]; + + /* Get source fullpath. */ + + ret = VfsNormalizePath(shellWorkingDirectory, src, &srcFullPath); + if (ret < 0) { + SetErrno(-ret); + PRINTK("cp error:%s\n", strerror(errno)); + return -1; + } + + if (src[strlen(src) - 1] == '/') { + PRINTK("cp %s error: Source file can't be a directory.\n", src); + goto errout_with_srcpath; + } + + /* Get dest fullpath. */ + ret = VfsNormalizePath(shellWorkingDirectory, dst, &drcFullPath); + if (ret < 0) { + SetErrno(-ret); + PRINTK("cp error: can't open %s. %s\n", dst, strerror(errno)); + goto errout_with_srcpath; + } + + /* Is dest path exist? */ + + ret = stat(drcFullPath, &statBuf); + if (ret < 0) { + /* Is dest path a directory? */ + if (dst[strlen(dst) - 1] == '/') { + PRINTK("cp error: %s, %s.\n", drcFullPath, strerror(errno)); + goto errout_with_path; + } + } else { + if ((S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode)) && dst[strlen(dst) - 1] == '/') { + PRINTK("cp error: %s is not a directory.\n", drcFullPath); + goto errout_with_path; + } + } + + if (OsIsContainersWildcard(srcFullPath)) { + if (ret < 0 || S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode)) { + char *srcCopy = strdup(srcFullPath); + if (srcCopy == NULL) { + PRINTK("cp error : Out of memory.\n"); + goto errout_with_path; + } + (void)OsWildcardExtractDirectory(srcCopy, &count, CP_COUNT); + free(srcCopy); + if (count > 1) { + PRINTK("cp error : %s is not a directory.\n", drcFullPath); + goto errout_with_path; + } + } + ret = OsWildcardExtractDirectory(srcFullPath, drcFullPath, CP_FILE); + } else { + ret = OsShellCmdDoCp(srcFullPath, drcFullPath); + } + free(drcFullPath); + free(srcFullPath); + return ret; + +errout_with_path: + free(drcFullPath); +errout_with_srcpath: + free(srcFullPath); + return VFS_ERROR; +} + +static inline void PrintRmUsage(void) +{ + PRINTK("rm [FILE] or rm [-r/-R] [FILE]\n"); +} + +int OsShellCmdRm(int argc, const char **argv) +{ + int ret; + char *fullpath = NULL; + const char *filename = NULL; + char *shellWorkingDirectory = OsShellGetWorkingDirtectory(); + + if (shellWorkingDirectory == NULL) { + return -1; + } + + ERROR_OUT_IF(argc != 1 && argc != 2, PrintRmUsage(), return -1); + + if (argc == 2) { + ERROR_OUT_IF(strcmp(argv[0], "-r") != 0 && strcmp(argv[0], "-R") != 0, PrintRmUsage(), return -1); + + filename = argv[1]; + ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath); + ERROR_OUT_IF(ret < 0, SetErr(-ret, "rm error"), return -1); + + if (OsIsContainersWildcard(fullpath)) { + ret = OsWildcardExtractDirectory(fullpath, NULL, RM_RECURSIVER); + } else { + ret = OsShellCmdDoRmdir(fullpath); + } + } else { + filename = argv[0]; + ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath); + ERROR_OUT_IF(ret < 0, SetErr(-ret, "rm error"), return -1); + + if (OsIsContainersWildcard(fullpath)) { + ret = OsWildcardExtractDirectory(fullpath, NULL, RM_FILE); + } else { + ret = unlink(fullpath); + } + } + if (ret == -1) { + perror("rm error"); + } + free(fullpath); + return 0; +} + +int OsShellCmdRmdir(int argc, const char **argv) +{ + int ret; + char *fullpath = NULL; + const char *filename = NULL; + char *shellWorkingDirectory = OsShellGetWorkingDirtectory(); + if (shellWorkingDirectory == NULL) { + return -1; + } + + ERROR_OUT_IF(argc == 0, PRINTK("rmdir [DIRECTORY]\n"), return -1); + + filename = argv[0]; + ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath); + ERROR_OUT_IF(ret < 0, SetErr(-ret, "rmdir error"), return -1); + + if (OsIsContainersWildcard(fullpath)) { + ret = OsWildcardExtractDirectory(fullpath, NULL, RM_DIR); + } else { + ret = rmdir(fullpath); + } + if (ret == -1) { + PRINTK("rmdir %s failed. Error: %s.\n", fullpath, strerror(errno)); + } + free(fullpath); + + return 0; +} + diff --git a/config.gni b/config.gni new file mode 100644 index 00000000..d9c0f837 --- /dev/null +++ b/config.gni @@ -0,0 +1,42 @@ +# Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. +# Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +declare_args() { + enable_ohos_kernel_liteos_m_cppsupport = true + enable_ohos_kernel_liteos_m_cpup = true + enable_ohos_kernel_liteos_m_exchook = true + enable_ohos_kernel_liteos_m_kal = true + enable_ohos_kernel_liteos_m_fs = true + enable_ohos_kernel_liteos_m_shell = false + enable_ohos_kernel_liteos_m_backtrace = true + enable_ohos_kernel_liteos_m_test = false + enable_ohos_kernel_liteos_m_pm = true + enable_ohos_kernel_liteos_m_lwip = false + ohos_kernel_liteos_m_lwip_path = "components/net/lwip-2.1:lwip" +}