bore

Unnamed repository
Log | Files | Refs | README

commit b641f1292c3ebdb92a831d9548b712eb5a00d1c3
parent 897bff6fc9e2b8446e9b6f6b43d9d158f86857b9
Author: phoebos <ben@bvnf.space>
Date:   Thu, 23 Sep 2021 01:40:31 +0100

nonfunctional ed

Diffstat:
MMakefile | 1+
MPROGRESS | 1+
Aed.c | 177+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 179 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -3,6 +3,7 @@ BINS = \ cat \ echo \ + ed \ false \ ls \ tee \ diff --git a/PROGRESS b/PROGRESS @@ -13,6 +13,7 @@ [ ] dirname [ ] du [x] echo +[ ] ed [x] false [ ] find [ ] grep diff --git a/ed.c b/ed.c @@ -0,0 +1,177 @@ +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +int s_flag; +char prompt; + +/* buf is a pointer to the bit we're working on at the moment, + * while buf_start stores the beginning of our data. + */ +char *buf, *buf_start; +int buf_size = BUFSIZ; +int buf_used = 0; + +void +print_byte_counts(size_t n) { + if (!s_flag) + printf("%zu\n", n); +} + +int +read_buf(char *path) { + int fd; + ssize_t n = 0; + + fd = open(path, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "ed: %s: %s\n", path, strerror(errno)); + return -1; + } + do { + if (buf_used >= buf_size) { + int size_new = buf_size * 3 / 2; + char *b_new = realloc(buf_start, size_new); + buf_start = b_new; + buf = buf_start + buf_used; + buf_size = size_new; + } + n = read(fd, buf, buf_size - buf_used); + buf_used += n; + } while (n > 0); + if (n == -1) { + fprintf(stderr, "ed: %s: %s\n", path, strerror(errno)); + return -1; + } + close(fd); + print_byte_counts(buf_used); + return 0; +} + +int +write_buf(char *path) { + int fd; + ssize_t n; + + fd = open(path, O_WRONLY); + if (fd == -1) { + fprintf(stderr, "ed: %s: %s\n", path, strerror(errno)); + return -1; + } + n = write(fd, buf_start, buf_used); + if (n == -1) { + fprintf(stderr, "ed: %s: %s\n", path, strerror(errno)); + return -1; + } + printf("%ld\n", n); + close(fd); + return 0; +} + + +/* set buf appropriately so that input() reads into the right bit. */ +void +input(void) { + ssize_t n; + char *tmp = malloc(BUFSIZ); + size_t len = BUFSIZ; + while (1) { + n = getline(&tmp, &len, stdin); + /* getline returns bytes + 1 for \n delimiter */ + if (n == 0) + return; + if (n < 0) { + fprintf(stderr, "ed: %s\n", strerror(errno)); + return; + } + if (tmp[0] == '.' && tmp[1] == '\n' && tmp[2] == '\0') + return; + memcpy(buf, tmp, n); + buf += n; + buf_used += n; + } +} + +int +ed(char *startfile) { + if (startfile) + if (read_buf(startfile) != 0) + return 1; + while (1) { + + if (prompt) + printf("%c ", prompt); + fflush(stdout); + int c = fgetc(stdin); + switch (c) { + case 'i': + buf = buf_start; + input(); + break; + case 'a': + buf += buf_used; + input(); + break; + case 'p': + printf("%s", buf_start); + break; + case 'w': + if (startfile) + write_buf(startfile); + else + printf("? writing to a new filename not yet implemented\n"); + break; + case 'q': + return 0; + case '\n': + break; + default: + printf("?\n"); + break; + } + } + return 0; +} + +void +usage_quit(char *argv0) { + fprintf(stderr, "usage: %s [-p prompt] [-s] [file]\n", argv0); + exit(1); +} + +int +main(int argc, char **argv) { + s_flag = 0; + prompt = 0; + int c; + + buf_start = malloc(buf_size); + buf = buf_start; + while ((c = getopt(argc, argv, "p:s")) != EOF) { + switch (c) { + case 's': + s_flag = 1; + break; + case 'p': + prompt = optarg[0]; + break; + case '?': + usage_quit(*argv); + break; + } + } + if (argc - optind > 1) + usage_quit(*argv); + + argv += optind; + + char *startfile = NULL; + if (*argv) + startfile = *argv; + + ed(startfile); + return 0; +}