summaryrefslogtreecommitdiff
path: root/src/commands
diff options
context:
space:
mode:
authorTyler Murphy <tylerm@tylerm.dev>2023-04-27 14:38:16 -0400
committerTyler Murphy <tylerm@tylerm.dev>2023-04-27 14:38:16 -0400
commit88d3515ae85924b8aea8c0546d33451ee369b7dd (patch)
treea5b825af7959d79bbd00f0dcfa5987671cb84c1a /src/commands
downloadlazysphere-88d3515ae85924b8aea8c0546d33451ee369b7dd.tar.gz
lazysphere-88d3515ae85924b8aea8c0546d33451ee369b7dd.tar.bz2
lazysphere-88d3515ae85924b8aea8c0546d33451ee369b7dd.zip
initial
Diffstat (limited to 'src/commands')
-rw-r--r--src/commands/cat.c152
-rw-r--r--src/commands/dd.c59
-rw-r--r--src/commands/yes.c26
3 files changed, 237 insertions, 0 deletions
diff --git a/src/commands/cat.c b/src/commands/cat.c
new file mode 100644
index 0000000..e2c471b
--- /dev/null
+++ b/src/commands/cat.c
@@ -0,0 +1,152 @@
+#include "../command.h"
+
+#include <ctype.h>
+#include <string.h>
+
+struct Flags {
+ bool number_lines;
+ bool number_non_empty;
+ bool change_non_print;
+ bool change_tabs;
+ bool end_lines_dollar;
+};
+
+static bool printable(char c) {
+ switch (c) {
+ case '\n': return true;
+ case '\r': return true;
+ case '\b': return true;
+ case '\t': return true;
+ default: return isprint(c);
+ }
+}
+
+static void help() {
+ printf("Usage: cat [-nbvteA] [FILE]...\n\n");
+ printf("Print FILEs to stdout\n\n");
+ printf("-n Number output lines\n");
+ printf("-b Number nonempty lines\n");
+ printf("-v Show nonprinting characters as ^x or M-x\n");
+ printf("-t ...and tabs as ^I\n");
+ printf("-e ...and end lines with $\n");
+ printf("-A Same as -vte\n");
+ exit(EXIT_SUCCESS);
+}
+
+static void cat_file(FILE* file, struct Flags flags) {
+ char c;
+ size_t read;
+
+ size_t line = 1;
+ bool empty = true;
+ bool newline = true;
+
+ while ((read = fread(&c, 1, 1, file)) != 0) {
+ if (c == '\n') {
+ if (empty && flags.number_lines) {
+ printf("\t%ld ", line);
+ }
+ if (flags.end_lines_dollar) {
+ printf("$");
+ }
+ line++;
+ newline = true;
+ empty = true;
+ goto print;
+ } else {
+ empty = false;
+ }
+
+ if (!newline) {
+ goto print;
+ }
+
+ if (!empty && (flags.number_non_empty || flags.number_lines)) {
+ printf("\t%ld ", line);
+ newline = false;
+ }
+ print:
+ if (!flags.change_non_print || printable(c)) {
+ if (flags.change_tabs && c == '\t') {
+ fwrite("^I", 1, 2, stdout);
+ } else {
+ fwrite(&c, 1, 1, stdout);
+ }
+ } else {
+ c |= '@';
+ fwrite(&c, 1, 1, stdout);
+ }
+ }
+}
+
+COMMAND(cat) {
+
+ struct Flags flags;
+ flags.number_lines = false;
+ flags.number_non_empty = false;
+ flags.change_non_print = false;
+ flags.change_tabs = false;
+ flags.end_lines_dollar = false;
+
+ for (int i = 0; i < argc; i++) {
+ if (!prefix("-", argv[i])) {
+ continue;
+ }
+
+ if (streql("--help", argv[i])) {
+ help();
+ }
+
+ size_t len = strlen(argv[i] + 1);
+ for (size_t j = 0; j < len; j++) {
+ char c = argv[i][j + 1];
+ switch (c) {
+ case 'n':
+ flags.number_lines = true;
+ break;
+ case 'b':
+ flags.number_non_empty = true;
+ break;
+ case 'v':
+ flags.change_non_print = true;
+ break;
+ case 't':
+ flags.change_non_print = true;
+ flags.change_tabs = true;
+ break;
+ case 'e':
+ flags.change_non_print = true;
+ flags.end_lines_dollar = true;
+ break;
+ case 'A':
+ flags.change_non_print = true;
+ flags.change_tabs = true;
+ flags.end_lines_dollar = true;
+ break;
+ default:
+ error("error: unkown flag -%c", c);
+ }
+ }
+ }
+
+ bool files = false;
+ for (int i = 0; i < argc; i++) {
+ if (streql("-", argv[i])) {
+ files = true;
+ cat_file(stdin, flags);
+ } else if (prefix("-", argv[i])) {
+ continue;
+ } else {
+ files = true;
+ FILE* in = get_file(argv[i], "r");
+ cat_file(in, flags);
+ fclose(in);
+ }
+ }
+
+ if (!files) {
+ cat_file(stdin, flags);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/commands/dd.c b/src/commands/dd.c
new file mode 100644
index 0000000..278dee3
--- /dev/null
+++ b/src/commands/dd.c
@@ -0,0 +1,59 @@
+#include "../command.h"
+#include <stdio.h>
+
+static void help() {
+ printf("Usage: dd [if=FILE] [of=FILE] [bs=N] [count=N]\n\n");
+ printf("Copy a file with converting and formatting\n\n");
+ printf("if=FILE\t\tRead from FILE instead of stdin\n");
+ printf("of=FILE\t\tWrite to FILE instead of stdout\n");
+ printf("bs=N\t\tRead and write N bytes at a time\n");
+ printf("count=N\t\tCopy only N input blocks\n");
+ exit(EXIT_SUCCESS);
+}
+
+COMMAND(dd) {
+
+ FILE* in_file = stdin;
+ FILE* out_file = stdout;
+ int bs = 1024;
+ int count = -1;
+
+ for (int i = 0; i < argc; i++) {
+ if (prefix("if=", argv[i])) {
+ char* path = argv[i] + 3;
+ in_file = get_file(path, "rb");
+ } else if (prefix("of=", argv[i])) {
+ char* path = argv[i] + 3;
+ out_file = get_file(path, "wb");
+ } else if (prefix("bs=", argv[i])) {
+ char* str = argv[i] + 3;
+ bs = get_number(str);
+ if (bs < 1) {
+ error("error: block size must be greater than 0");
+ }
+ } else if (prefix("count=", argv[i])) {
+ char* str = argv[i] + 6;
+ count = get_number(str);
+ if (count < 1) {
+ error("error: count must be greather than 0");
+ }
+ } else if (streql("--help", argv[i])) {
+ help();
+ } else {
+ error("error: unkown option %s", argv[i]);
+ }
+ }
+
+ char* buffer = malloc(bs);
+ size_t read;
+ while ((read = fread(buffer, 1, bs, in_file)) != 0) {
+ fwrite(buffer, 1, read, out_file);
+ if (--count, count == 0) break;
+ }
+
+ free(buffer);
+ fclose(in_file);
+ fclose(out_file);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/commands/yes.c b/src/commands/yes.c
new file mode 100644
index 0000000..c954810
--- /dev/null
+++ b/src/commands/yes.c
@@ -0,0 +1,26 @@
+#include "../command.h"
+
+static void help() {
+ printf("Usage: yes [STRING]\n\n");
+ printf("Repeatedly output a line with all specified STRING(s), or 'y'.\n");
+ exit(EXIT_SUCCESS);
+}
+
+COMMAND(yes) {
+ const char* repeat;
+ if (argc == 0) {
+ repeat = "y";
+ } else {
+ if (streql("--help", argv[0])) {
+ help();
+ }
+ repeat = argv[0];
+ for (int i = 1; i < argc; i++) {
+ *(argv[i]-1) = ' ';
+ }
+ }
+
+ while (true) {
+ printf("%s\n", repeat);
+ }
+}