aboutsummaryrefslogtreecommitdiff
path: root/user/usr/bin/wc.c
diff options
context:
space:
mode:
authornthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
committernthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
commitc63f340d90800895f007de64b7d2d14624263331 (patch)
tree2c0849fa597dd6da831c8707b6f2603403778d7b /user/usr/bin/wc.c
Created student weenix repository
Diffstat (limited to 'user/usr/bin/wc.c')
-rw-r--r--user/usr/bin/wc.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/user/usr/bin/wc.c b/user/usr/bin/wc.c
new file mode 100644
index 0000000..f622614
--- /dev/null
+++ b/user/usr/bin/wc.c
@@ -0,0 +1,114 @@
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define BUFFER_SIZE 1024
+
+typedef struct count_results
+{
+ unsigned long long n_chars;
+ unsigned long long n_words;
+ unsigned long long n_lines;
+} count_results_t;
+
+char buf[BUFFER_SIZE];
+
+void print_counts(count_results_t *results, char *name)
+{
+ if (name)
+ {
+ printf("%10llu %10llu %10llu %10s\n", results->n_lines,
+ results->n_words, results->n_chars, name);
+ }
+ else
+ {
+ printf("%10llu %10llu %10llu\n", results->n_lines, results->n_words,
+ results->n_chars);
+ }
+}
+
+void count(int fd, char *name, count_results_t *results)
+{
+ size_t bytes_read;
+ unsigned int in_word, i;
+
+ in_word = 0;
+ while ((bytes_read = read(fd, buf, BUFFER_SIZE)) > 0)
+ {
+ for (i = 0; i < bytes_read; ++i)
+ {
+ if (isspace(buf[i]))
+ {
+ if (in_word)
+ {
+ results->n_words++;
+ in_word = 0;
+ }
+ }
+ else
+ {
+ in_word = 1;
+ }
+
+ if (buf[i] == '\n')
+ {
+ results->n_lines++;
+ }
+ }
+
+ results->n_chars += bytes_read;
+ }
+
+ print_counts(results, name);
+}
+
+int main(int argc, char **argv)
+{
+ int f, fd;
+ count_results_t total_counts = {.n_chars = 0, .n_words = 0, .n_lines = 0};
+ count_results_t local_counts = {.n_chars = 0, .n_words = 0, .n_lines = 0};
+
+ if (argc == 1)
+ {
+ /* Reading from standard input. */
+ count(0, 0, &total_counts);
+ }
+ else
+ {
+ /* Reading files, not standard input. */
+ for (f = 1; f < argc; ++f)
+ {
+ fd = open(argv[f], O_RDONLY, 0);
+ if (fd < 0)
+ {
+ /* Error opening file. */
+ fprintf(stderr, "wc: %s: open: %s\n", argv[f], strerror(errno));
+ }
+ else
+ {
+ /* Opened the file. */
+ count(fd, argv[f], &local_counts);
+
+ total_counts.n_chars += local_counts.n_chars;
+ total_counts.n_words += local_counts.n_words;
+ total_counts.n_lines += local_counts.n_lines;
+
+ /* Reset the local counts. */
+ local_counts.n_chars = local_counts.n_words =
+ local_counts.n_lines = 0;
+
+ close(fd);
+ }
+ }
+
+ if (argc > 2)
+ {
+ /* They provided multiple files. We should print the total too. */
+ print_counts(&total_counts, "total");
+ }
+ }
+
+ return 0;
+}