diff --git a/samples/posix/uname/CMakeLists.txt b/samples/posix/uname/CMakeLists.txt new file mode 100644 index 000000000000000..82257e7cc7d8e17 --- /dev/null +++ b/samples/posix/uname/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(posix_uname) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/posix/uname/prj.conf b/samples/posix/uname/prj.conf new file mode 100644 index 000000000000000..47e3b82e5ce925c --- /dev/null +++ b/samples/posix/uname/prj.conf @@ -0,0 +1,3 @@ +CONFIG_POSIX_API=y +CONFIG_SHELL=y +CONFIG_SHELL_GETOPT=y diff --git a/samples/posix/uname/sample.yaml b/samples/posix/uname/sample.yaml new file mode 100644 index 000000000000000..cfe990eb127d359 --- /dev/null +++ b/samples/posix/uname/sample.yaml @@ -0,0 +1,22 @@ +sample: + description: posix uname sample + name: posix uname +common: + tags: posix + filter: not CONFIG_ARCH_POSIX + integration_platforms: + - native_posix_64 + - qemu_riscv64 + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - "sysname\\[7\\]: Zephyr" + - "nodename\\[\\d+\\]: .*" + - "release\\[\\d+\\]: \\d+\\.\\d+\\.\\d+" + - "version\\[\\d+\\]: .*" + - "machine\\[\\d+\\]: .*" +tests: + sample.posix.uname: + tags: uname diff --git a/samples/posix/uname/src/main.c b/samples/posix/uname/src/main.c new file mode 100644 index 000000000000000..7cf4cad7aa07f8c --- /dev/null +++ b/samples/posix/uname/src/main.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +#include +#include + +int main(void) +{ + struct utsname info; + + uname(&info); + + printk("\nPrinting everything in utsname...\n"); + printk("sysname[%zu]: %s\n", sizeof(info.sysname), info.sysname); + printk("nodename[%zu]: %s\n", sizeof(info.nodename), info.nodename); + printk("release[%zu]: %s\n", sizeof(info.release), info.release); + printk("version[%zu]: %s\n", sizeof(info.version), info.version); + printk("machine[%zu]: %s\n", sizeof(info.machine), info.machine); + + return 0; +} + +#define UNAME_KERNEL (1 << 0) +#define UNAME_NODE (1 << 1) +#define UNAME_RELEASE (1 << 2) +#define UNAME_VERSION (1 << 3) +#define UNAME_MACHINE (1 << 4) +#define UNAME_PLATFORM (1 << 5) +#define UNAME_UNKNOWN (1 << 6) +#define UNAME_ALL \ + (UNAME_KERNEL | UNAME_NODE | UNAME_RELEASE | UNAME_VERSION | UNAME_MACHINE | UNAME_PLATFORM) +void getopt_init(void); +static int uname_cmd_handler(const struct shell *sh, size_t argc, char **argv) +{ + struct utsname info; + unsigned int set; + int option; + bool badarg; + bool first; + int ret; + int i; + + set = 0; + badarg = false; + + /* Get the uname options */ + + optind = 1; + while ((option = getopt(argc, argv, "asonrvmpi")) != -1) { + switch (option) { + case 'a': + set = UNAME_ALL; + break; + + case 'o': + case 's': + set |= UNAME_KERNEL; + break; + + case 'n': + set |= UNAME_NODE; + break; + + case 'r': + set |= UNAME_RELEASE; + break; + + case 'v': + set |= UNAME_VERSION; + break; + + case 'm': + set |= UNAME_MACHINE; + break; + + case 'p': + if (set != UNAME_ALL) { + set |= UNAME_UNKNOWN; + } + break; + + case 'i': + set |= UNAME_PLATFORM; + break; + + case '?': + default: + badarg = true; + break; + } + } + + /* If a bad argument was encountered, then return without processing the + * command + */ + + if (badarg) { + struct getopt_state *state = getopt_state_get(); + + shell_error(sh, "uname: illegal option -- %c", state->optopt); + shell_print(sh, "usage: uname [-asonrvmpi]"); + return -1; + } + + /* If nothing is provided on the command line, the default is -s */ + + if (set == 0) { + set = UNAME_KERNEL; + } + + /* Get uname data */ + + ret = uname(&info); + if (ret < 0) { + shell_error(sh, "uname: returned %d", ret); + return -1; + } + + /* Process each option */ + + first = true; + for (i = 0; set != 0; i++) { + unsigned int mask = (1 << i); + + if ((set & mask) != 0) { + set &= ~mask; + switch (i) { + case 0: /* print the kernel/operating system name */ + shell_fprintf(sh, SHELL_NORMAL, "%s", info.sysname); + break; + + case 1: /* Print nodename */ + shell_fprintf(sh, SHELL_NORMAL, "%s", info.nodename); + break; + + case 2: /* Print the kernel release */ + shell_fprintf(sh, SHELL_NORMAL, "%s", info.release); + break; + + case 3: /* Print the kernel version */ + shell_fprintf(sh, SHELL_NORMAL, "%s", info.version); + break; + + case 4: /* Print the machine hardware name */ + shell_fprintf(sh, SHELL_NORMAL, "%s", info.machine); + break; + + case 5: /* Print the machine platform name */ + shell_fprintf(sh, SHELL_NORMAL, "%s", CONFIG_BOARD); + break; + + case 6: /* Print "unknown" */ + shell_fprintf(sh, SHELL_NORMAL, "%s", "unknown"); + break; + + default: + shell_error(sh, "uname: illegal option -- %d", i); + return -1; + } + + shell_fprintf(sh, SHELL_NORMAL, " "); + } + } + + shell_fprintf(sh, SHELL_NORMAL, "\n"); + + return 0; +} + +SHELL_CMD_REGISTER(uname, NULL, NULL, uname_cmd_handler);