1 /*
2 * Copyright (c) 2016,2019 Daichi GOTO
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "command.h"
29
30 #define BUFLEN 65536
31
32 int
main(int argc,char * argv[])33 main(int argc, char *argv[])
34 {
35 getcmdargs(argc, argv, "hvD", CMDARGS_R_NONE);
36
37 int rfd;
38 int wfd;
39
40 ssize_t nr, nw;
41 int off;
42
43 char buf[BUFLEN];
44 char *p;
45
46 bool outputed; // Holds whether data is output or not
47 bool tagremoved; // Holds whether tag is removed or not
48
49 wfd = fileno(stdout);
50
51 /*
52 * Process the first file
53 */
54 rfd = open(F_ARGV[1], O_RDONLY);
55 if (-1 == rfd)
56 err(EX_NOINPUT, "%s", F_ARGV[1]);
57
58 tagremoved = false;
59 outputed = false;
60 nw = 0;
61 while ((nr = read(rfd, buf, BUFLEN)) > 0) {
62 for (off = 0; nr; nr -= nw, off += nw) {
63 // Skip tags
64 if (!tagremoved) {
65 p = buf;
66 while ('\n' != *p && '\0' != *p) {
67 ++p;
68 ++off;
69 }
70 if ('\n' == *p) {
71 ++off;
72 tagremoved = true;
73 }
74 nr -= off;
75 }
76
77 // If the read data is all tags, move to the next
78 // read without outputting
79 if (0 >= nr)
80 break;
81
82 if ((nw = write(wfd, buf + off, (size_t)nr)) < 0)
83 err(1, "stdout");
84 outputed = true;
85 }
86 }
87
88 // If there is no line feed at the end of the file, an additional
89 // line break is output.
90 if (outputed && '\n' != buf[off + nr - 1])
91 putchar('\n');
92
93 close(rfd);
94
95 // Flush the standard output before processing the next file.
96 // If this processing is not performed, the output may go wrong.
97 fflush(stdout);
98
99 /*
100 * Process second and subsequent files
101 */
102 for (int file_i = 2; file_i <= F_ARGC; file_i++) {
103 rfd = open(F_ARGV[file_i], O_RDONLY);
104 if (-1 == rfd)
105 err(EX_NOINPUT, "%s", F_ARGV[1]);
106
107 outputed = false;
108 nw = 0;
109 while ((nr = read(rfd, buf, BUFLEN)) > 0) {
110 for (off = 0; nr; nr -= nw, off += nw) {
111 if ((nw = write(wfd, buf + off,
112 (size_t)nr)) < 0)
113 err(1, "stdout");
114 outputed = true;
115 }
116 }
117
118 // If there is no line feed at the end of the file, an
119 // additional line break is output.
120 if (outputed && '\n' != buf[off + nr - 1])
121 putchar('\n');
122
123 close(rfd);
124
125 // Flush the standard output before processing the next
126 // file. If this processing is not performed, the output
127 // may go wrong.
128 fflush(stdout);
129 }
130
131 exit(EX_OK);
132 }
133