Upload Tizen:Base source
[framework/base/util-linux-ng.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
44 static void doskip(const char *, int);
45 static u_char *get(void);
46
47 #ifndef MIN
48 #define MIN(a,b) ((a)<(b)?(a):(b))
49 #endif
50
51 enum _vflag vflag = FIRST;
52
53 static off_t address;                   /* address/offset in stream */
54 static off_t eaddress;                  /* end address */
55
56 static inline void
57 print(PR *pr, u_char *bp) {
58
59         switch(pr->flags) {
60         case F_ADDRESS:
61                 (void)printf(pr->fmt, (quad_t)address);
62                 break;
63         case F_BPAD:
64                 (void)printf(pr->fmt, "");
65                 break;
66         case F_C:
67                 conv_c(pr, bp);
68                 break;
69         case F_CHAR:
70                 (void)printf(pr->fmt, *bp);
71                 break;
72         case F_DBL:
73             {
74                 double dval;
75                 float fval;
76                 switch(pr->bcnt) {
77                 case 4:
78                         memmove(&fval, bp, sizeof(fval));
79                         (void)printf(pr->fmt, fval);
80                         break;
81                 case 8:
82                         memmove(&dval, bp, sizeof(dval));
83                         (void)printf(pr->fmt, dval);
84                         break;
85                 }
86                 break;
87             }
88         case F_INT:
89             {
90                 short sval;     /* int16_t */
91                 int ival;       /* int32_t */
92                 long long Lval; /* int64_t, quad_t */
93
94                 switch(pr->bcnt) {
95                 case 1:
96                         (void)printf(pr->fmt, (quad_t)*bp);
97                         break;
98                 case 2:
99                         memmove(&sval, bp, sizeof(sval));
100                         (void)printf(pr->fmt, (quad_t)sval);
101                         break;
102                 case 4:
103                         memmove(&ival, bp, sizeof(ival));
104                         (void)printf(pr->fmt, (quad_t)ival);
105                         break;
106                 case 8:
107                         memmove(&Lval, bp, sizeof(Lval));
108                         (void)printf(pr->fmt, (quad_t)Lval);
109                         break;
110                 }
111                 break;
112             }
113         case F_P:
114                 (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
115                 break;
116         case F_STR:
117                 (void)printf(pr->fmt, (char *)bp);
118                 break;
119         case F_TEXT:
120                 (void)printf("%s", pr->fmt);
121                 break;
122         case F_U:
123                 conv_u(pr, bp);
124                 break;
125         case F_UINT:
126             {
127                 unsigned short sval;    /* u_int16_t */
128                 unsigned int ival;      /* u_int32_t */
129                 unsigned long long Lval;/* u_int64_t, u_quad_t */
130
131                 switch(pr->bcnt) {
132                 case 1:
133                         (void)printf(pr->fmt, (u_quad_t)*bp);
134                         break;
135                 case 2:
136                         memmove(&sval, bp, sizeof(sval));
137                         (void)printf(pr->fmt, (u_quad_t)sval);
138                         break;
139                 case 4:
140                         memmove(&ival, bp, sizeof(ival));
141                         (void)printf(pr->fmt, (u_quad_t)ival);
142                         break;
143                 case 8:
144                         memmove(&Lval, bp, sizeof(Lval));
145                         (void)printf(pr->fmt, (u_quad_t)Lval);
146                         break;
147                 }
148                 break;
149             }
150         }
151 }
152
153 static void bpad(PR *pr)
154 {
155         static const char *spec = " -0+#";
156         char *p1, *p2;
157
158         /*
159          * remove all conversion flags; '-' is the only one valid
160          * with %s, and it's not useful here.
161          */
162         pr->flags = F_BPAD;
163         pr->cchar[0] = 's';
164         pr->cchar[1] = 0;
165         for (p1 = pr->fmt; *p1 != '%'; ++p1);
166         for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
167         while ((*p2++ = *p1++) != 0) ;
168 }
169
170 void display(void)
171 {
172         register FS *fs;
173         register FU *fu;
174         register PR *pr;
175         register int cnt;
176         register u_char *bp;
177         off_t saveaddress;
178         u_char savech = 0, *savebp;
179
180         while ((bp = get()) != NULL)
181             for (fs = fshead, savebp = bp, saveaddress = address; fs;
182                 fs = fs->nextfs, bp = savebp, address = saveaddress)
183                     for (fu = fs->nextfu; fu; fu = fu->nextfu) {
184                         if (fu->flags&F_IGNORE)
185                                 break;
186                         for (cnt = fu->reps; cnt; --cnt)
187                             for (pr = fu->nextpr; pr; address += pr->bcnt,
188                                 bp += pr->bcnt, pr = pr->nextpr) {
189                                     if (eaddress && address >= eaddress &&
190                                         !(pr->flags&(F_TEXT|F_BPAD)))
191                                             bpad(pr);
192                                     if (cnt == 1 && pr->nospace) {
193                                         savech = *pr->nospace;
194                                         *pr->nospace = '\0';
195                                     }
196                                     print(pr, bp);
197                                     if (cnt == 1 && pr->nospace)
198                                         *pr->nospace = savech;
199                             }
200                     }
201         if (endfu) {
202                 /*
203                  * if eaddress not set, error or file size was multiple of
204                  * blocksize, and no partial block ever found.
205                  */
206                 if (!eaddress) {
207                         if (!address)
208                                 return;
209                         eaddress = address;
210                 }
211                 for (pr = endfu->nextpr; pr; pr = pr->nextpr)
212                         switch(pr->flags) {
213                         case F_ADDRESS:
214                                 (void)printf(pr->fmt, (quad_t)eaddress);
215                                 break;
216                         case F_TEXT:
217                                 (void)printf("%s", pr->fmt);
218                                 break;
219                         }
220         }
221 }
222
223 static char **_argv;
224
225 static u_char *
226 get(void)
227 {
228         static int ateof = 1;
229         static u_char *curp, *savp;
230         int n;
231         int need, nread;
232         u_char *tmpp;
233
234         if (!curp) {
235                 curp = emalloc(blocksize);
236                 savp = emalloc(blocksize);
237         } else {
238                 tmpp = curp;
239                 curp = savp;
240                 savp = tmpp;
241                 address += blocksize;
242         }
243         for (need = blocksize, nread = 0;;) {
244                 /*
245                  * if read the right number of bytes, or at EOF for one file,
246                  * and no other files are available, zero-pad the rest of the
247                  * block and set the end flag.
248                  */
249                 if (!length || (ateof && !next(NULL))) {
250                         if (need == blocksize)
251                                 return(NULL);
252                         if (!need && vflag != ALL &&
253                             !memcmp(curp, savp, nread)) {
254                                 if (vflag != DUP)
255                                         (void)printf("*\n");
256                                 return(NULL);
257                         }
258                         if (need > 0)
259                                 memset((char *)curp + nread, 0, need);
260                         eaddress = address + nread;
261                         return(curp);
262                 }
263                 n = fread((char *)curp + nread, sizeof(u_char),
264                     length == -1 ? need : MIN(length, need), stdin);
265                 if (!n) {
266                         if (ferror(stdin))
267                                 (void)fprintf(stderr, "hexdump: %s: %s\n",
268                                     _argv[-1], strerror(errno));
269                         ateof = 1;
270                         continue;
271                 }
272                 ateof = 0;
273                 if (length != -1)
274                         length -= n;
275                 if (!(need -= n)) {
276                         if (vflag == ALL || vflag == FIRST ||
277                             memcmp(curp, savp, blocksize)) {
278                                 if (vflag == DUP || vflag == FIRST)
279                                         vflag = WAIT;
280                                 return(curp);
281                         }
282                         if (vflag == WAIT)
283                                 (void)printf("*\n");
284                         vflag = DUP;
285                         address += blocksize;
286                         need = blocksize;
287                         nread = 0;
288                 }
289                 else
290                         nread += n;
291         }
292 }
293
294 int next(char **argv)
295 {
296         static int done;
297         int statok;
298
299         if (argv) {
300                 _argv = argv;
301                 return(1);
302         }
303         for (;;) {
304                 if (*_argv) {
305                         if (!(freopen(*_argv, "r", stdin))) {
306                                 (void)fprintf(stderr, "hexdump: %s: %s\n",
307                                     *_argv, strerror(errno));
308                                 exitval = 1;
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                         (void)fprintf(stderr, "hexdump: %s: %s.\n",
336                             fname, strerror(errno));
337                         exit(1);
338                 }
339                 if (S_ISREG(sbuf.st_mode) && skip >= sbuf.st_size) {
340                   /* If size valid and skip >= size */
341                         skip -= sbuf.st_size;
342                         address += sbuf.st_size;
343                         return;
344                 }
345         }
346         /* sbuf may be undefined here - do not test it */
347         if (fseek(stdin, skip, SEEK_SET)) {
348                 (void)fprintf(stderr, "hexdump: %s: %s.\n",
349                     fname, strerror(errno));
350                 exit(1);
351         }
352         address += skip;
353         skip = 0;
354 }
355
356 void *
357 emalloc(int sz) {
358         void *p;
359
360         if (!(p = malloc((u_int)sz)))
361                 nomem();
362         memset(p, 0, sz);
363         return(p);
364 }
365
366 void nomem() {
367         (void)fprintf(stderr, "hexdump: %s.\n", strerror(errno));
368         exit(1);
369 }