commit 25063680dc66013d98d541104f0d50c4967c18dc
parent bfd05a231834e67d6bf0732c287769c7c8231569
Author: aabacchus <ben@bvnf.space>
Date: Tue, 14 Sep 2021 19:05:23 +0100
head: rewrite using getopt and open, read rather than fopen,fgetc
Diffstat:
M | src/head.c | | | 61 | ++++++++++++++++++++++++++++++++++++++----------------------- |
1 file changed, 38 insertions(+), 23 deletions(-)
diff --git a/src/head.c b/src/head.c
@@ -1,27 +1,31 @@
#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
int
-head(FILE *file, int lines)
+head(int fd, int lines)
{
- if(file == NULL) {
- fprintf(stderr, "head: %s\n", strerror(errno));
- return 1;
- }
int a;
+ ssize_t r;
int c = 0;
- while((a = fgetc(file)) != EOF) {
- if(a == '\n')
+ while((r = read(fd, &a, 1)) > 0) {
+ if(r == -1) {
+ fprintf(stderr, "head: %s\n", strerror(errno));
+ return 1;
+ }
+ if((char)a == '\n')
++c;
putchar(a);
if(c == lines)
- return lines;
+ break;
}
- return lines;
+ return 0;
}
int
@@ -29,21 +33,32 @@ main(int argc, char *argv[])
{
int lines = 10;
int return_value = 0;
- switch(argc) {
- case 1:
- return_value = head(stdin, lines);
- break;
- case 2:
- return_value = head(fopen(argv[1], "r"), lines);
- break;
- case 3:
- lines = abs(atoi(argv[1]));
- return_value = head(fopen(argv[2], "r"), lines);
- break;
- default:
- lines = atoi(argv[2]);
- return_value = head(fopen(argv[3], "r"), lines);
+ int c, fd;
+ c = getopt(argc, argv, "n:");
+ switch(c) {
+ case 'n':
+ lines = atoi(optarg);
+ if(lines == 0) {
+ fprintf(stderr, "head: invalid number '%s'\n", optarg);
+ return 1;
+ }
break;
+ case ':':
+ case '?':
+ fprintf(stderr, "usage: head [-n N] file\n");
+ return 1;
+ }
+
+ if(optind == argc)
+ fd = 0;
+ else {
+ fd = open(argv[optind], O_RDONLY);
+ if(fd == -1) {
+ fprintf(stderr, "head: %s: %s\n", argv[optind], strerror(errno));
+ return 1;
+ }
}
+ return_value = head(fd, lines);
+ close(fd);
return return_value;
}