174 lines
4.2 KiB
C
174 lines
4.2 KiB
C
/*
|
|
*----------------------------------------------------------------------
|
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
|
* <jeang3nie@HitchHiker-Linux.org> wrote this file. As long as you
|
|
* retain this notice you can do whatever you want with this stuff. If
|
|
* we meet some day, and you think this stuff is worth it, you can buy
|
|
* me a beer in return.
|
|
* ---------------------------------------------------------------------
|
|
* ______ _______ _ _________
|
|
* ( __ \ ( ___ )( ( /|( )\__ __/
|
|
* | ( \ )| ( ) || \ ( ||/ ) (
|
|
* | | ) || | | || \ | | | |
|
|
* | | | || | | || (\ \) | | |
|
|
* | | ) || | | || | \ | | |
|
|
* | (__/ )| (___) || ) \ | | |
|
|
* (______/ (_______)|/ )_) )_(
|
|
*
|
|
* _______ _______ _ _________ _______
|
|
* ( ____ )( ___ )( \ /|\__ __/( ____ \
|
|
* | ( )|| ( ) || \ ( | ) ( | ( |/
|
|
* | (____)|| (___) || \ | | | | | |
|
|
* | _____)| ___ || (\ \) | | | | |
|
|
* | ( | ( ) || | \ | | | | |
|
|
* | ) | ) ( || ) \ |___) (___| (____|\
|
|
* |/ |/ \||/ \_)\_______/(_______/
|
|
*
|
|
*/
|
|
|
|
#define _GNU_SOURCE // getline, getopt
|
|
|
|
#include <ctype.h> // isprint
|
|
#include <err.h> // err, perror
|
|
#include <errno.h> // errno
|
|
#include <inttypes.h> // uint*_t
|
|
#include <libgen.h> // basename
|
|
#include <stdio.h> // fclose, fopen, getline, nread, perror, printf
|
|
#include <stdlib.h> // exit
|
|
#include <string.h> // strcmp
|
|
#include <unistd.h> // getopt
|
|
|
|
uint8_t cflag = 0, nflag = 0, qflag = 0, vflag = 0;
|
|
int lines = 10, j = 0, chars = 0;
|
|
static const char *__progname;
|
|
|
|
static void usage() {
|
|
fprintf(stderr, "Usage: %s [-hqv] [-c count] [-n lines] [FILE]...\n", __progname);
|
|
}
|
|
|
|
void _head(char *file) {
|
|
FILE *fp;
|
|
char *line = NULL;
|
|
size_t len = 0;
|
|
ssize_t nread;
|
|
int i = 0;
|
|
if (strcmp(file, "-") == 0)
|
|
fp = stdin;
|
|
else
|
|
fp = fopen(file, "r");
|
|
if (fp == NULL) {
|
|
perror("fopen");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (vflag) {
|
|
if (j)
|
|
printf("\n==> %s <==\n", file);
|
|
else
|
|
printf("==> %s <==\n", file);
|
|
}
|
|
if (cflag && !nflag) {
|
|
while (!feof(fp)) {
|
|
putchar(fgetc(fp));
|
|
i++;
|
|
if (i >= chars)
|
|
break;
|
|
}
|
|
} else {
|
|
while ((nread = getline(&line, &len, fp)) != -1) {
|
|
printf("%s", line);
|
|
i++;
|
|
if (i >= lines)
|
|
break;
|
|
}
|
|
free(line);
|
|
}
|
|
if (strcmp(file, "-") != 0) {
|
|
fclose(fp);
|
|
j = 1;
|
|
}
|
|
}
|
|
|
|
long parselong(char *buf) {
|
|
errno = 0;
|
|
char *endptr;
|
|
int num = strtol(optarg, &endptr, 10);
|
|
if (errno != 0) {
|
|
perror("Error parsing integer from input: ");
|
|
exit(EXIT_FAILURE);
|
|
} else if (num == 0 && endptr == optarg) {
|
|
fprintf(stderr, "Error: invalid input: %s\n", optarg);
|
|
exit(EXIT_FAILURE);
|
|
} else if (*endptr != '\0') {
|
|
fprintf(stderr, "Error: invalid input: %s\n", optarg);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
return num;
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int c, index;
|
|
__progname = basename(argv[0]);
|
|
|
|
/* Handle the old school -[0-9] style options */
|
|
if ((argv[1])[0] == '-' && isdigit((argv[1])[1])) {
|
|
char *x;
|
|
x = argv[1] + 1;
|
|
int i;
|
|
for (i = 0; i < sizeof(argv[1]); i++) {
|
|
if (!isdigit(x[i])) {
|
|
x[i] = '\0';
|
|
break;
|
|
}
|
|
}
|
|
lines = (int)strtol(x, NULL, 10);
|
|
}
|
|
|
|
while ((c = getopt(argc, argv, "c:hqvn:0123456789")) != -1)
|
|
switch (c) {
|
|
case 'c':
|
|
cflag = 1;
|
|
chars = (int)parselong(optarg);
|
|
break;
|
|
case 'q':
|
|
qflag = 1;
|
|
vflag = 0;
|
|
break;
|
|
case 'v':
|
|
if (!qflag)
|
|
vflag = 1;
|
|
break;
|
|
case 'h':
|
|
usage();
|
|
exit(EXIT_SUCCESS);
|
|
case 'n':
|
|
nflag = 1;
|
|
lines = (int)parselong(optarg);
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
break;
|
|
default:
|
|
usage();
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (argv[optind] == NULL)
|
|
_head("-");
|
|
|
|
if (argv[optind + 1] != NULL && (!qflag))
|
|
vflag = 1;
|
|
|
|
for (index = optind; index < argc; index++) {
|
|
_head(argv[index]);
|
|
}
|
|
return 0;
|
|
}
|