Unix Tools

Implementations of common Unix command-line utilities written in C.


unix-tools / head.c

head.c raw | download
1#define _POSIX_C_SOURCE 200809L
2#include <unistd.h>
3#include <errno.h>
4#include <inttypes.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9static int
10head(FILE *file, uintmax_t count, const char *name)
11{
12 char *line = NULL;
13 size_t capacity = 0;
14 int status = 0;
15 while (count--) {
16 ssize_t n = getline(&line, &capacity, file);
17 if (n < 0) {
18 if (!feof(file)) { perror(name); status = 1; }
19 break;
20 }
21 if (fwrite(line, 1, (size_t)n, stdout) != (size_t)n) {
22 perror("head: stdout"); status = 1; break;
23 }
24 }
25 free(line);
26 return status;
27}
28
29int
30main(int argc, char **argv)
31{
32 uintmax_t count = 10;
33 int option, status = 0;
34 while ((option = getopt(argc, argv, "n:")) != -1) {
35 char *end;
36 if (option != 'n') goto usage;
37 errno = 0;
38 if (!*optarg || strspn(optarg, "0123456789") != strlen(optarg)) goto usage;
39 count = strtoumax(optarg, &end, 10);
40 if (errno || *end) goto usage;
41 }
42 if (optind == argc) status = head(stdin, count, "head: stdin");
43 for (; optind < argc; ++optind) {
44 FILE *file = strcmp(argv[optind], "-") == 0 ? stdin : fopen(argv[optind], "r");
45 if (file == NULL) { perror(argv[optind]); status = 1; continue; }
46 status |= head(file, count, argv[optind]);
47 if (file != stdin && fclose(file) == EOF) { perror(argv[optind]); status = 1; }
48 }
49 if (fflush(stdout) == EOF) { perror("head: stdout"); status = 1; }
50 return status;
51usage:
52 fprintf(stderr, "usage: %s [-n number] [file...]\n", argv[0]);
53 return 1;
54}