lazysphere/src/commands/head.c

126 lines
2.9 KiB
C
Raw Normal View History

2023-04-29 00:32:18 +00:00
#include "../command.h"
2023-05-01 22:43:32 +00:00
static struct {
2023-04-29 00:32:18 +00:00
int count;
bool lines;
bool print_headers;
bool dont_print_headers;
2023-05-01 22:43:32 +00:00
} flags;
2023-04-29 00:32:18 +00:00
2023-05-01 22:43:32 +00:00
static void head_file_lines(FILE* file) {
2023-04-29 00:32:18 +00:00
size_t len = 0;
char* line = NULL;
2023-05-01 22:43:32 +00:00
int count = flags.count;
2023-04-29 00:32:18 +00:00
while(count > 0 && getline(&line, &len, file) != -1) {
printf("%s", line);
count--;
}
free(line);
fclose(file);
}
2023-05-01 22:43:32 +00:00
static void head_file_chars(FILE* file) {
2023-04-29 00:32:18 +00:00
char c;
2023-05-01 22:43:32 +00:00
int count = flags.count;
2023-04-29 00:32:18 +00:00
while(count > 0 && (c = getc(file)) != EOF) {
putchar(c);
count--;
}
fclose(file);
}
2023-05-01 22:43:32 +00:00
static void help(void) {
2023-04-29 00:32:18 +00:00
printf("Usage: head [OPTIONS] [FILE]...\n\n");
printf("Print first 10 lines of FILEs (or stdin)\n");
printf("With more than one FILE, precede each with a filename header.\n\n");
printf("\t-c [+]N[bkm]\tPrint first N bytes\n");
printf("\t-n N[bkm]\tPrint first N lines\n");
printf("\t\t\t(b:*512 k:*1024 m:*1024^2)\n");
printf("\t-q\t\tNever print headers\n");
printf("\t-v\t\tAlways print headers\n");
}
2023-05-01 22:43:32 +00:00
static void print_header(char* path, bool many) {
if (flags.dont_print_headers) return;
if (!many && !flags.print_headers) return;
2023-04-29 00:32:18 +00:00
if (streql("-", path)) {
printf("\n==> standard input <==\n");
} else {
printf("\n=>> %s <==\n", path);
}
}
2023-05-01 22:43:32 +00:00
static void head_file(char* path, bool many) {
2023-04-29 00:32:18 +00:00
FILE* file = get_file(path, "r");
2023-05-01 22:43:32 +00:00
print_header(path, many);
if (flags.lines) {
head_file_lines(file);
2023-04-29 00:32:18 +00:00
} else {
2023-05-01 22:43:32 +00:00
head_file_chars(file);
}
}
static int short_arg(char c, char* next) {
switch(c) {
case 'c': {
flags.lines = false;
check_arg(next);
long int bkm = get_blkm(next);
if (bkm < 1) {
2023-05-03 16:17:56 +00:00
error("bkm cannot be less than 1");
2023-05-01 22:43:32 +00:00
}
flags.count = bkm;
return ARG_USED;
}
case 'n': {
flags.lines = true;
check_arg(next);
long int bkm = get_blkm(next);
if (bkm < 1) {
2023-05-03 16:17:56 +00:00
error("bkm cannot be less than 1");
2023-05-01 22:43:32 +00:00
}
flags.count = bkm;
return ARG_USED;
}
case 'q':
flags.dont_print_headers = true;
break;
case 'v':
flags.print_headers = true;
break;
2023-05-03 16:17:56 +00:00
default:
return ARG_INVALID;
2023-04-29 00:32:18 +00:00
}
2023-05-01 22:43:32 +00:00
return ARG_UNUSED;
2023-04-29 00:32:18 +00:00
}
COMMAND(head) {
flags.count = 10;
flags.lines = true;
flags.print_headers = false;
flags.dont_print_headers = false;
2023-05-01 22:43:32 +00:00
int start = parse_args(argc, argv, help, short_arg, NULL);
2023-04-29 00:32:18 +00:00
int count = argc - start;
if (count < 1) {
2023-05-01 22:43:32 +00:00
head_file_lines(stdin);
2023-04-29 00:32:18 +00:00
return EXIT_SUCCESS;
}
if (count == 1) {
2023-05-01 22:43:32 +00:00
head_file(argv[start], false);
2023-04-29 00:32:18 +00:00
return EXIT_SUCCESS;
}
for (int i = 0; i < count; i++) {
2023-05-01 22:43:32 +00:00
head_file(argv[start + i], true);
2023-04-29 00:32:18 +00:00
}
return EXIT_SUCCESS;
}