cat: rewrite to use the splice() syscall
[lab.git] / head.c
blobfbfa3960a07569423debe10d29fd4fbac6b7e3f5
1 /* `head.c` - copy the first part of files
2 Copyright (c) 2022, Alan Potteiger
3 See `LICENSE` for copyright and license details */
5 #define _POSIX_C_SOURCE 200809L
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <unistd.h>
13 static const char *usage = {
14 "usage: head [-n number] [file...]\n"
17 static char *strstdin = "stdin";
19 int
20 main(int argc, char *argv[])
22 char ch;
23 char *linep;
24 int n, i, mult;
25 ssize_t s;
26 size_t linecapp;
27 FILE *f;
29 linep = NULL;
30 n = 10;
31 s = 0;
32 i = mult = 0;
33 linecapp = 0;
35 while ((ch = getopt(argc, argv, "n:")) != -1) {
36 switch (ch) {
37 case 'n':
38 linep = optarg;
39 n = (int) strtol(optarg, &linep, 10);
40 if (optarg == linep) {
41 fprintf(stderr, "head: invalid line number\n");
42 return 1;
45 if (n < 1) {
46 fprintf(stderr, "head: number is required to "
47 "be a positive decimal integer.\n");
48 return 1;
50 linep = NULL;
51 break;
52 case '?':
53 default:
54 fputs(usage, stderr);
55 return 1;
59 argc -= optind;
60 argv += optind;
62 /* head of stdin */
63 if (argc < 1) {
64 while (n > 0) {
65 s = getline(&linep, &linecapp, stdin);
66 if (s < 0)
67 break;
68 fwrite(linep, s, 1, stdout);
69 n--;
71 free(linep);
72 return 0;
75 if (argc > 1)
76 mult = 1;
78 /* head for listed input files */
79 for (;argc > 0; argc-- && argv++) {
80 if (argv[0][0] == '-' && argv[0][1] == '\0') {
81 f = stdin;
82 argv[0] = strstdin;
83 } else {
84 f = fopen(argv[0], "r");
86 if (f == NULL) {
87 fprintf(stderr, "head: %s: %s\n", argv[0],
88 strerror(errno));
89 break;
92 if (mult == 1)
93 printf("==> %s <==\n", argv[0]);
94 if (mult > 1)
95 printf("\n==> %s <==\n", argv[0]);
97 i = n;
98 while (i > 0) {
99 s = getline(&linep, &linecapp, f);
100 if (s < 0)
101 break;
102 fwrite(linep, s, 1, stdout);
103 i--;
106 mult++;
107 fclose(f);
109 free(linep);
111 return 0;