/* *---------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * 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 // isprint #include // err, perror #include // errno #include // uint*_t #include // basename #include // fclose, fopen, getline, nread, perror, printf #include // exit #include // strcmp #include // 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; }