]> git.ipfire.org Git - thirdparty/util-linux.git/blob - text-utils/display.c
po: update uk.po (from translationproject.org)
[thirdparty/util-linux.git] / text-utils / display.c
1 /*
2 * Copyright (c) 1989 The Regents of the University of California.
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
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include <sys/param.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <ctype.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include "hexdump.h"
43 #include "xalloc.h"
44 #include "c.h"
45 #include "nls.h"
46
47 static void doskip(const char *, int);
48 static u_char *get(void);
49
50 enum _vflag vflag = FIRST;
51
52 static off_t address; /* address/offset in stream */
53 static off_t eaddress; /* end address */
54
55 static inline void
56 print(PR *pr, unsigned char *bp) {
57
58 switch(pr->flags) {
59 case F_ADDRESS:
60 (void)printf(pr->fmt, (int64_t)address);
61 break;
62 case F_BPAD:
63 (void)printf(pr->fmt, "");
64 break;
65 case F_C:
66 conv_c(pr, bp);
67 break;
68 case F_CHAR:
69 (void)printf(pr->fmt, *bp);
70 break;
71 case F_DBL:
72 {
73 double dval;
74 float fval;
75 switch(pr->bcnt) {
76 case 4:
77 memmove(&fval, bp, sizeof(fval));
78 (void)printf(pr->fmt, fval);
79 break;
80 case 8:
81 memmove(&dval, bp, sizeof(dval));
82 (void)printf(pr->fmt, dval);
83 break;
84 }
85 break;
86 }
87 case F_INT:
88 {
89 short sval; /* int16_t */
90 int ival; /* int32_t */
91 long long Lval; /* int64_t, int64_t */
92
93 switch(pr->bcnt) {
94 case 1:
95 (void)printf(pr->fmt, (int64_t)*bp);
96 break;
97 case 2:
98 memmove(&sval, bp, sizeof(sval));
99 (void)printf(pr->fmt, (int64_t)sval);
100 break;
101 case 4:
102 memmove(&ival, bp, sizeof(ival));
103 (void)printf(pr->fmt, (int64_t)ival);
104 break;
105 case 8:
106 memmove(&Lval, bp, sizeof(Lval));
107 (void)printf(pr->fmt, (int64_t)Lval);
108 break;
109 }
110 break;
111 }
112 case F_P:
113 (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
114 break;
115 case F_STR:
116 (void)printf(pr->fmt, (char *)bp);
117 break;
118 case F_TEXT:
119 (void)printf("%s", pr->fmt);
120 break;
121 case F_U:
122 conv_u(pr, bp);
123 break;
124 case F_UINT:
125 {
126 unsigned short sval; /* u_int16_t */
127 unsigned int ival; /* u_int32_t */
128 unsigned long long Lval;/* u_int64_t, u_int64_t */
129
130 switch(pr->bcnt) {
131 case 1:
132 (void)printf(pr->fmt, (uint64_t)*bp);
133 break;
134 case 2:
135 memmove(&sval, bp, sizeof(sval));
136 (void)printf(pr->fmt, (uint64_t)sval);
137 break;
138 case 4:
139 memmove(&ival, bp, sizeof(ival));
140 (void)printf(pr->fmt, (uint64_t)ival);
141 break;
142 case 8:
143 memmove(&Lval, bp, sizeof(Lval));
144 (void)printf(pr->fmt, (uint64_t)Lval);
145 break;
146 }
147 break;
148 }
149 }
150 }
151
152 static void bpad(PR *pr)
153 {
154 static const char *spec = " -0+#";
155 char *p1, *p2;
156
157 /*
158 * remove all conversion flags; '-' is the only one valid
159 * with %s, and it's not useful here.
160 */
161 pr->flags = F_BPAD;
162 pr->cchar[0] = 's';
163 pr->cchar[1] = 0;
164 for (p1 = pr->fmt; *p1 != '%'; ++p1);
165 for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
166 while ((*p2++ = *p1++) != 0) ;
167 }
168
169 void display(void)
170 {
171 register FS *fs;
172 register FU *fu;
173 register PR *pr;
174 register int cnt;
175 register unsigned char *bp;
176 off_t saveaddress;
177 unsigned char savech = 0, *savebp;
178
179 while ((bp = get()) != NULL)
180 for (fs = fshead, savebp = bp, saveaddress = address; fs;
181 fs = fs->nextfs, bp = savebp, address = saveaddress)
182 for (fu = fs->nextfu; fu; fu = fu->nextfu) {
183 if (fu->flags&F_IGNORE)
184 break;
185 for (cnt = fu->reps; cnt; --cnt)
186 for (pr = fu->nextpr; pr; address += pr->bcnt,
187 bp += pr->bcnt, pr = pr->nextpr) {
188 if (eaddress && address >= eaddress &&
189 !(pr->flags&(F_TEXT|F_BPAD)))
190 bpad(pr);
191 if (cnt == 1 && pr->nospace) {
192 savech = *pr->nospace;
193 *pr->nospace = '\0';
194 }
195 print(pr, bp);
196 if (cnt == 1 && pr->nospace)
197 *pr->nospace = savech;
198 }
199 }
200 if (endfu) {
201 /*
202 * if eaddress not set, error or file size was multiple of
203 * blocksize, and no partial block ever found.
204 */
205 if (!eaddress) {
206 if (!address)
207 return;
208 eaddress = address;
209 }
210 for (pr = endfu->nextpr; pr; pr = pr->nextpr)
211 switch(pr->flags) {
212 case F_ADDRESS:
213 (void)printf(pr->fmt, (int64_t)eaddress);
214 break;
215 case F_TEXT:
216 (void)printf("%s", pr->fmt);
217 break;
218 }
219 }
220 }
221
222 static char **_argv;
223
224 static u_char *
225 get(void)
226 {
227 static int ateof = 1;
228 static u_char *curp, *savp;
229 ssize_t n, need, nread;
230 u_char *tmpp;
231
232 if (!curp) {
233 curp = xcalloc(1, blocksize);
234 savp = xcalloc(1, blocksize);
235 } else {
236 tmpp = curp;
237 curp = savp;
238 savp = tmpp;
239 address += blocksize;
240 }
241 for (need = blocksize, nread = 0;;) {
242 /*
243 * if read the right number of bytes, or at EOF for one file,
244 * and no other files are available, zero-pad the rest of the
245 * block and set the end flag.
246 */
247 if (!length || (ateof && !next(NULL))) {
248 if (need == blocksize)
249 return(NULL);
250 if (!need && vflag != ALL &&
251 !memcmp(curp, savp, nread)) {
252 if (vflag != DUP)
253 (void)printf("*\n");
254 return(NULL);
255 }
256 if (need > 0)
257 memset((char *)curp + nread, 0, need);
258 eaddress = address + nread;
259 return(curp);
260 }
261 if (fileno(stdin) == -1) {
262 warnx(_("all input file arguments failed"));
263 return(NULL);
264 }
265 n = fread((char *)curp + nread, sizeof(unsigned char),
266 length == -1 ? need : min(length, need), stdin);
267 if (!n) {
268 if (ferror(stdin))
269 warn("%s", _argv[-1]);
270 ateof = 1;
271 continue;
272 }
273 ateof = 0;
274 if (length != -1)
275 length -= n;
276 if (!(need -= n)) {
277 if (vflag == ALL || vflag == FIRST ||
278 memcmp(curp, savp, blocksize)) {
279 if (vflag == DUP || vflag == FIRST)
280 vflag = WAIT;
281 return(curp);
282 }
283 if (vflag == WAIT)
284 (void)printf("*\n");
285 vflag = DUP;
286 address += blocksize;
287 need = blocksize;
288 nread = 0;
289 }
290 else
291 nread += n;
292 }
293 }
294
295 int next(char **argv)
296 {
297 static int done;
298 int statok;
299
300 if (argv) {
301 _argv = argv;
302 return(1);
303 }
304 for (;;) {
305 if (*_argv) {
306 if (!(freopen(*_argv, "r", stdin))) {
307 warn("%s", *_argv);
308 exitval = EXIT_FAILURE;
309 ++_argv;
310 continue;
311 }
312 statok = done = 1;
313 } else {
314 if (done++)
315 return(0);
316 statok = 0;
317 }
318 if (skip)
319 doskip(statok ? *_argv : "stdin", statok);
320 if (*_argv)
321 ++_argv;
322 if (!skip)
323 return(1);
324 }
325 /* NOTREACHED */
326 }
327
328 static void
329 doskip(const char *fname, int statok)
330 {
331 struct stat sbuf;
332
333 if (statok) {
334 if (fstat(fileno(stdin), &sbuf))
335 err(EXIT_FAILURE, "%s", fname);
336 if (S_ISREG(sbuf.st_mode) && skip > sbuf.st_size) {
337 /* If size valid and skip >= size */
338 skip -= sbuf.st_size;
339 address += sbuf.st_size;
340 return;
341 }
342 }
343 /* sbuf may be undefined here - do not test it */
344 if (fseek(stdin, skip, SEEK_SET))
345 err(EXIT_FAILURE, "%s", fname);
346 address += skip;
347 skip = 0;
348 }