diff options
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/Makefile | 1 | ||||
-rw-r--r-- | usr.bin/cat/cat.c | 54 | ||||
-rw-r--r-- | usr.bin/fetch/fetch.c | 67 | ||||
-rw-r--r-- | usr.bin/osh/osh.c | 6 | ||||
-rw-r--r-- | usr.bin/sysctl/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/sysctl/sysctl.c | 279 |
6 files changed, 402 insertions, 11 deletions
diff --git a/usr.bin/Makefile b/usr.bin/Makefile index d8bf421..47ba752 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -26,3 +26,4 @@ all: make -C oasm/ $(ARGS) make -C oemu/ $(ARGS) make -C dmidump/ $(ARGS) + make -C sysctl/ $(ARGS) diff --git a/usr.bin/cat/cat.c b/usr.bin/cat/cat.c index 35e9e95..4fb74d1 100644 --- a/usr.bin/cat/cat.c +++ b/usr.bin/cat/cat.c @@ -34,12 +34,27 @@ #include <stdio.h> #include <stdlib.h> +#define NUM_MODE_NONE 0 +#define NUM_MODE_ALL 1 +#define NUM_MODE_NONBLANK 2 + +static void +help(void) +{ + printf( + "usage: cat <flags> <file>\n" + "[-b] do not number blank lines\n" + "[-n] number all lines\n" + ); +} + static void -cat(const char *pathname) +cat(const char *pathname, int num_mode) { FILE *file; char buf[64]; int fd; + size_t lineno = 1; file = fopen(pathname, "r"); if (file == NULL) { @@ -47,7 +62,21 @@ cat(const char *pathname) } while (fgets(buf, sizeof(buf), file) != NULL) { + switch (num_mode) { + case NUM_MODE_NONE: + break; + case NUM_MODE_ALL: + printf("%d ", lineno); + break; + case NUM_MODE_NONBLANK: + if (buf[0] == '\n') { + break; + } + printf("%d ", lineno); + break; + } printf("%s", buf); + ++lineno; } fclose(file); @@ -56,8 +85,27 @@ cat(const char *pathname) int main(int argc, char **argv) { - for (size_t i = 1; i < argc; ++i) { - cat(argv[i]); + int num_mode = NUM_MODE_NONE; + int c; + + if (argc < 2) { + help(); + return -1; + } + + while ((c = getopt(argc, argv, "nb")) != -1) { + switch (c) { + case 'n': + num_mode = NUM_MODE_ALL; + break; + case 'b': + num_mode = NUM_MODE_NONBLANK; + break; + } + } + + for (size_t i = optind; i < argc; ++i) { + cat(argv[i], num_mode); } return 0; diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c index 175cd0e..1e8ef92 100644 --- a/usr.bin/fetch/fetch.c +++ b/usr.bin/fetch/fetch.c @@ -30,21 +30,76 @@ #include <unistd.h> #include <fcntl.h> #include <string.h> +#include <stdlib.h> #include <stdio.h> -static const char *user = "unknown"; +#define CPUID(level, a, b, c, d) \ + __ASMV("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)) #define ASCII_ART \ " ____ \n" \ - " | \\__\\ \n" \ - " | /\\ \\ user: %s\n" \ - " |/ \\ \\ OS: Hyra/amd64 v"_OSVER"\n" \ - " \\ R. \\ \\ arch: "_OSARCH"\n" \ + " | \\__\\ user: %s\n" \ + " | /\\ \\ OS: Hyra/amd64 v"_OSVER"\n" \ + " |/ \\ \\ arch: "_OSARCH"\n" \ + " \\ R. \\ \\ cpu: %s\n" \ " \\ I. \\ \\\n" + +/* + * Get the processor brand string + * + * @buffer: Buffer to copy branch string + * + * Returns a pointer to newly allocated memory + * containing the vendor string. One must ensure + * to call free() after use. + */ +static char * +get_brand(void) +{ + uint32_t eax, ebx, ecx, edx; + uint32_t regs[12]; + char buf[sizeof(regs) + 1]; + char *p = buf; + + /* Can we even get the brand? */ + CPUID(0x80000000, eax, ebx, ecx, edx); + if (eax < 0x80000004) { + return NULL; + } + + CPUID(0x80000002, regs[0], regs[1], regs[2], regs[3]); + CPUID(0x80000003, regs[4], regs[5], regs[6], regs[7]); + CPUID(0x80000004, regs[8], regs[9], regs[10], regs[11]); + + /* Log it */ + memcpy(p, regs, sizeof(regs)); + buf[sizeof(regs)] = '\0'; + + /* Strip away leading whitespaces */ + for (int i = 0; i < sizeof(buf); ++i) { + if (buf[i] == ' ') { + ++p; + } else { + break; + } + } + + return strdup(p); +} + int main(void) { - printf(ASCII_ART, getlogin()); + char *brand = get_brand(); + + if (brand == NULL) { + brand = strdup("unknown"); + } + + printf(ASCII_ART, getlogin(), brand); + free(brand); return 0; } diff --git a/usr.bin/osh/osh.c b/usr.bin/osh/osh.c index 545f95a..5062e64 100644 --- a/usr.bin/osh/osh.c +++ b/usr.bin/osh/osh.c @@ -67,7 +67,7 @@ "clear - Clear the screen\n" \ "exit - Exit the shell" -#define PROMPT "[%s::osmora]~ " +#define PROMPT "[%s::%s]~ " static char last_command[INPUT_SIZE]; static char buf[INPUT_SIZE]; @@ -466,6 +466,7 @@ main(int argc, char **argv) { int found, prog_argc; int stdout_fd; + char hostname[128] = "osmora"; uint8_t buf_i; char *p; char c; @@ -478,9 +479,10 @@ main(int argc, char **argv) running = 1; bell_fd = open("/dev/beep", O_WRONLY); dump_file("/etc/motd"); + gethostname(hostname, sizeof(hostname)); while (running) { - printf(PROMPT, getlogin()); + printf(PROMPT, getlogin(), hostname); buf_i = getstr(); if (buf[0] == '\0') { diff --git a/usr.bin/sysctl/Makefile b/usr.bin/sysctl/Makefile new file mode 100644 index 0000000..e32dbc4 --- /dev/null +++ b/usr.bin/sysctl/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/sysctl: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/sysctl/sysctl.c b/usr.bin/sysctl/sysctl.c new file mode 100644 index 0000000..d4275a7 --- /dev/null +++ b/usr.bin/sysctl/sysctl.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * 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 Hyra 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 OWNER 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 <sys/sysctl.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <stdbool.h> + +#define BUF_SIZE 128 + +/* Kern var string constants */ +#define NAME_OSTYPE "ostype" +#define NAME_OSRELEASE "osrelease" +#define NAME_VERSION "version" +#define NAME_VCACHE_TYPE "vcache_type" + +/* Hw var string constants */ +#define NAME_PAGESIZE "pagesize" +#define NAME_NCPU "ncpu" +#define NAME_MACHINE "machine" + +/* Name start string constants */ +#define NAME_KERN "kern" +#define NAME_HW "hw" + +/* Name start int constants */ +#define NAME_DEF_KERN 0 +#define NAME_DEF_HW 1 + +/* + * Print the contents read from a sysctl + * variable depending on its type. + * + * @data: Data to print + * @is_str: True if a string + */ +static inline void +varbuf_print(char data[BUF_SIZE], bool is_str) +{ + uint32_t *val; + + if (is_str) { + printf("%s\n", data); + } else { + val = (uint32_t *)data; + printf("%d\n", *val); + } +} + +/* + * Convert string name to a internal name + * definition. + * + * @name: Name to convert + * + * Convert to int def + * / + * kern.ostype + * ^^ + * + * -- + * Returns a less than zero value on failure + * (e.g., entry not found). + */ +static int +name_to_def(const char *name) +{ + switch (*name) { + case 'k': + if (strcmp(name, NAME_KERN) == 0) { + return NAME_DEF_KERN; + } + + return -1; + case 'h': + if (strcmp(name, NAME_HW) == 0) { + return NAME_DEF_HW; + } + + return -1; + } + + return -1; +} + +/* + * Handle parsing of 'kern.*' node names + * + * @node: Node name to parse + * @is_str: Set to true if string + */ +static int +kern_node(const char *node, bool *is_str) +{ + switch (*node) { + case 'v': + if (strcmp(node, NAME_VERSION) == 0) { + return KERN_VERSION; + } + + if (strcmp(node, NAME_VCACHE_TYPE) == 0) { + return KERN_VCACHE_TYPE; + } + return -1; + case 'o': + if (strcmp(node, NAME_OSTYPE) == 0) { + return KERN_OSTYPE; + } + + if (strcmp(node, NAME_OSRELEASE) == 0) { + return KERN_OSRELEASE; + } + return -1; + } + + return -1; +} + +/* + * Handle parsing of 'hw.*' node names + * + * @node: Node name to parse + * @is_str: Set to true if string + */ +static int +hw_node(const char *node, bool *is_str) +{ + switch (*node) { + case 'p': + if (strcmp(node, NAME_PAGESIZE) == 0) { + *is_str = false; + return HW_PAGESIZE; + } + + return -1; + case 'n': + if (strcmp(node, NAME_NCPU) == 0) { + *is_str = false; + return HW_NCPU; + } + + return -1; + case 'm': + if (strcmp(node, NAME_MACHINE) == 0) { + return HW_MACHINE; + } + return -1; + } + + return -1; +} + +/* + * Convert string node to a sysctl name + * definition. + * + * @name: Name to convert + * @is_str: Set to true if string + * + * Convert to int def + * / + * kern.ostype + * ^^ name + * + * -- + * Returns a less than zero value on failure + * (e.g., entry not found). + */ +static int +node_to_def(int name, const char *node, bool *is_str) +{ + int retval; + bool dmmy; + + /* + * If the caller did not set `is_str' just + * set it to a dummy value. Otherwise, we will + * make it *default* to a 'true' value. + */ + if (is_str == NULL) { + is_str = &dmmy; + } else { + *is_str = true; + } + + switch (name) { + case NAME_DEF_KERN: + return kern_node(node, is_str); + case NAME_DEF_HW: + return hw_node(node, is_str); + } + + return -1; +} + +int +main(int argc, char **argv) +{ + struct sysctl_args args; + char *var, *p; + int type, error; + int root, name; + size_t oldlen; + bool is_str; + char buf[BUF_SIZE]; + + if (argc < 2) { + printf("sysctl: usage: sysctl <var>\n"); + return -1; + } + + var = argv[1]; + p = strtok(var, "."); + + if (p == NULL) { + printf("sysctl: bad var\n"); + return -1; + } + + if ((root = name_to_def(p)) < 0) { + printf("sysctl: bad var \"%s\"", p); + return root; + } + + p = strtok(NULL, "."); + if (p == NULL) { + printf("sysctl: bad var \"%s\"\n", p); + return -1; + } + + if ((name = node_to_def(root, p, &is_str)) < 0) { + printf("sysctl: bad var \"%s\"\n", p); + return name; + } + + memset(buf, 0, sizeof(buf)); + oldlen = sizeof(buf); + args.name = &name; + args.nlen = 1; + args.oldp = buf; + args.oldlenp = &oldlen; + args.newp = NULL; + args.newlen = 0; + + if ((error = sysctl(&args)) != 0) { + printf("sysctl returned %d\n", error); + return error; + } + + varbuf_print(buf, is_str); + return 0; +} |