From 38f0bc3e82f04641491846ef36b5aab0744e1368 Mon Sep 17 00:00:00 2001 From: Vasiliy Edomin Date: Tue, 18 Aug 2020 14:57:06 +0600 Subject: [PATCH] Add unix shell sample --- README.md | 3 + unix/shell/.gitignore | 1 + unix/shell/Makefile | 14 ++++ unix/shell/main.c | 178 ++++++++++++++++++++++++++++++++++++++++++ unix/shell/main.o | Bin 0 -> 13896 bytes 5 files changed, 196 insertions(+) create mode 100644 unix/shell/.gitignore create mode 100644 unix/shell/Makefile create mode 100644 unix/shell/main.c create mode 100644 unix/shell/main.o diff --git a/README.md b/README.md index 68fe265..5e67916 100644 --- a/README.md +++ b/README.md @@ -38,5 +38,8 @@ Directory structure: - tasm/scripts - some common scripts for building and running examples with DosBox - tasm/dos_input_hex - Example of input HEX byte in DL. +* [**unix/shell**](https://github.com/edomin/samples/tree/master/unix/shell) - +envoking unix utils by typing its name in stdin. It is not complete shell +because it can not do piping and can not process shell syntax. Source code of samples released to public domain (license CC0). \ No newline at end of file diff --git a/unix/shell/.gitignore b/unix/shell/.gitignore new file mode 100644 index 0000000..03e813f --- /dev/null +++ b/unix/shell/.gitignore @@ -0,0 +1 @@ +shell \ No newline at end of file diff --git a/unix/shell/Makefile b/unix/shell/Makefile new file mode 100644 index 0000000..ae6446f --- /dev/null +++ b/unix/shell/Makefile @@ -0,0 +1,14 @@ +CC = gcc +CFLAGS = -Wall -Wextra -Wshadow -Wno-unused-parameter -Wno-unused-variable \ + -O0 -ggdb +LD = gcc +LDFLAGS = + +shell: main.o + $(LD) $(LDFLAGS) -o shell main.o + +main.o: main.c + $(CC) $(CFLAGS) -c main.c -o main.o + +run: shell + ./shell diff --git a/unix/shell/main.c b/unix/shell/main.c new file mode 100644 index 0000000..f0728a9 --- /dev/null +++ b/unix/shell/main.c @@ -0,0 +1,178 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define COMMAND_LEN_MAX 1024 +#define TOKEN_LEN_MAX COMMAND_LEN_MAX +#define TOKENS_MAX 256 + +/* https://gist.github.com/Fonger/98cc95ac39fbe1a7e4d9 */ +size_t strlcat(char *dst, const char *src, size_t size) { + size_t srclen; + size_t dstlen; + + dstlen = strlen(dst); + size -= dstlen + 1; + + if (!size) + return (dstlen); + + srclen = strlen(src); + + if (srclen > size) + srclen = size; + + memcpy(dst + dstlen, src, srclen); + dst[dstlen + srclen] = '\0'; + + return (dstlen + srclen); +} + +size_t strlcpy(char *dst, const char *src, size_t size) { + size_t srclen; + + size --; + + srclen = strlen(src); + + if (srclen > size) + srclen = size; + + memcpy(dst, src, srclen); + dst[srclen] = '\0'; + + return (srclen); +} + +void Prompt(void) { + char username[LOGIN_NAME_MAX]; + char hostname[HOST_NAME_MAX]; + char workingDir[PATH_MAX]; + size_t promptMax = LOGIN_NAME_MAX + HOST_NAME_MAX + PATH_MAX + 4; + char prompt[promptMax]; + + getlogin_r(username, LOGIN_NAME_MAX); + gethostname(hostname, HOST_NAME_MAX); + getcwd(workingDir, PATH_MAX); + + strlcpy(prompt, username, promptMax); + strlcat(prompt, "@", promptMax); + strlcat(prompt, hostname, promptMax); + strlcat(prompt, ":", promptMax); + strlcat(prompt, workingDir, promptMax); + strlcat(prompt, "$ ", promptMax); + + printf("%s", prompt); +} + +void ReadCommand(char *command, size_t len) { + fgets(command, len, stdin); + command[strlen(command) - 1] = '\0'; +} + +void Tokenize(char *command, char **tokens, size_t *tokensCount, + size_t tokensMax, size_t tokenLenMax) { + char *pch; + + *tokensCount = 0; + + pch = strtok(command," "); + while (pch != NULL) { + strlcpy(tokens[*tokensCount], pch, tokenLenMax); + pch = strtok(NULL, " "); + (*tokensCount)++; + if (*tokensCount > tokensMax) + break; + } +} + +bool IsNumber(char *str, size_t len) { + bool number = true; + + for (size_t i = 0; i < len; i++) { + if (str[i] == '\0') { + if (i == 0) { + number = false; + } + break; + } + if (!isdigit(str[i])) { + number = false; + break; + } + } + + return number; +} + +void InitTokens(char **tokens, size_t len) { + for (size_t i = 0; i < len; i++) { + tokens[i] = NULL; + } +} + +void RefreshTokens(char **tokens, size_t len) { + for (size_t i = 0; i < len; i++) { + if (tokens[i] == NULL) + tokens[i] = malloc(sizeof(char) * len); + } +} + +void NullTerminateTokens(char **tokens, size_t len, size_t tokensCount) { + for (size_t i = tokensCount; i < len; i++) { + free(tokens[i]); + tokens[i] = NULL; + } +} + +int main(int argc, char **argv) { + char command[COMMAND_LEN_MAX]; + char **tokens = malloc(sizeof(char *) * TOKENS_MAX); + size_t tokensCount; + int status; + int exitStatus = 0; + + InitTokens(tokens, TOKENS_MAX); + + while (true) { + RefreshTokens(tokens, TOKENS_MAX); + + Prompt(); + ReadCommand(command, COMMAND_LEN_MAX); + Tokenize(command, tokens, &tokensCount, TOKENS_MAX, TOKEN_LEN_MAX); + + NullTerminateTokens(tokens, TOKENS_MAX, tokensCount); + + if (strncmp(tokens[0], "exit", TOKEN_LEN_MAX) == 0) { + if (tokens[1] == NULL) { + return exitStatus; + } else { + if (IsNumber(tokens[1], TOKEN_LEN_MAX)) + return strtol(tokens[1], NULL, 10); + else + return exitStatus; + } + } + + if (fork() != 0) { + /* parent */ + waitpid(-1, &status, 0); + exitStatus = WEXITSTATUS(status); + } else { + /* child */ + int ret = execvp(tokens[0], tokens); + if (ret != 0) { + perror("execve"); + return 0; + } + } + } + + return 0; +} diff --git a/unix/shell/main.o b/unix/shell/main.o new file mode 100644 index 0000000000000000000000000000000000000000..8aa7412eeb384e0ea1ce5316636a51d1d5903065 GIT binary patch literal 13896 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 LF{S2SP5u7{MUKmk literal 0 HcmV?d00001