1 /* @(#)dump.c 1.42 20/05/05 joerg */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)dump.c 1.42 20/05/05 joerg";
6 #endif
7 /*
8 * File dump.c - dump a file/device both in hex and in ASCII.
9 *
10 * Written by Eric Youngdale (1993).
11 *
12 * Copyright 1993 Yggdrasil Computing, Incorporated
13 * Copyright (c) 1999-2020 J. Schilling
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2
17 * as published by the Free Software Foundation.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License along with
25 * this program; see the file COPYING. If not, write to the Free Software
26 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29 #include <schily/stdlib.h>
30 #include <schily/unistd.h>
31 #include <schily/string.h>
32 #include <schily/utypes.h>
33
34 #include <schily/stdio.h>
35 #include <schily/standard.h>
36 #include <schily/termios.h>
37 #include <schily/signal.h>
38 #include <schily/schily.h>
39 #include <schily/nlsdefs.h>
40
41 #include "../scsi.h"
42 #include "cdrdeflt.h"
43 #include "../../cdrecord/version.h"
44
45 /*
46 * Note: always use these macros to avoid problems.
47 *
48 * ISO_ROUND_UP(X) may cause an integer overflow and thus give
49 * incorrect results. So avoid it if possible.
50 *
51 * ISO_BLOCKS(X) is overflow safe. Prefer this when ever it is possible.
52 */
53 #define SECTOR_SIZE (2048)
54 #define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
55 #define ISO_BLOCKS(X) (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
56
57 #define infile in_image
58 EXPORT FILE *infile = NULL;
59 EXPORT BOOL ignerr = FALSE;
60 LOCAL off_t file_addr;
61 LOCAL off_t sec_addr = (off_t)-1;
62 LOCAL Uchar sector[2048];
63 #define PAGE 256
64 LOCAL Uchar buffer[PAGE];
65 LOCAL Uchar search[64];
66
67 #ifdef USE_V7_TTY
68 LOCAL struct sgttyb savetty;
69 LOCAL struct sgttyb newtty;
70 #else
71 #ifdef USE_TERMIOS
72 LOCAL struct termios savetty;
73 LOCAL struct termios newtty;
74 #endif
75 #endif
76
77 LOCAL void reset_tty __PR((void));
78 LOCAL void set_tty __PR((void));
79 LOCAL void onsusp __PR((int sig));
80 LOCAL void crsr2 __PR((int row, int col));
81 LOCAL void readblock __PR((void));
82 LOCAL void showblock __PR((int flag));
83 LOCAL int getbyte __PR((void));
84 LOCAL void usage __PR((int excode));
85 EXPORT int main __PR((int argc, char *argv[]));
86
87 LOCAL void
reset_tty()88 reset_tty()
89 {
90 #ifdef USE_V7_TTY
91 if (ioctl(STDIN_FILENO, TIOCSETN, &savetty) == -1) {
92 #else
93 #ifdef USE_TERMIOS
94 #ifdef TCSANOW
95 if (tcsetattr(STDIN_FILENO, TCSANOW, &savetty) == -1) {
96 #else
97 if (ioctl(STDIN_FILENO, TCSETAF, &savetty) == -1) {
98 #endif
99 #else /* USE_TERMIOS */
100 if (0) {
101 #endif /* USE_TERMIOS */
102 #endif
103 printf(_("Cannot put tty into normal mode\n"));
104 exit(1);
105 }
106 }
107
108 LOCAL void
109 set_tty()
110 {
111 #ifdef USE_V7_TTY
112 if (ioctl(STDIN_FILENO, TIOCSETN, &newtty) == -1) {
113 #else
114 #ifdef USE_TERMIOS
115 #ifdef TCSANOW
116 if (tcsetattr(STDIN_FILENO, TCSANOW, &newtty) == -1) {
117 #else
118 if (ioctl(STDIN_FILENO, TCSETAF, &newtty) == -1) {
119 #endif
120 #else /* USE_TERMIOS */
121 if (0) {
122 #endif /* USE_TERMIOS */
123 #endif
124 printf(_("Cannot put tty into raw mode\n"));
125 exit(1);
126 }
127 }
128
129
130 /*
131 * Come here when we get a suspend signal from the terminal
132 */
133 LOCAL void
134 onsusp(sig)
135 int sig;
136 {
137 #ifdef SIGTTOU
138 /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
139 signal(SIGTTOU, SIG_IGN);
140 #endif
141 reset_tty();
142 fflush(stdout);
143 #ifdef SIGTTOU
144 signal(SIGTTOU, SIG_DFL);
145 /* Send the TSTP signal to suspend our process group */
146 signal(SIGTSTP, SIG_DFL);
147 /* sigsetmask(0);*/
148 kill(0, SIGTSTP);
149 /* Pause for station break */
150
151 /* We're back */
152 signal(SIGTSTP, onsusp);
153 #endif
154 set_tty();
155 }
156
157
158 LOCAL void
159 crsr2(row, col)
160 int row;
161 int col;
162 {
163 printf("\033[%d;%dH", row, col);
164 }
165
166 LOCAL void
167 readblock()
168 {
169 off_t dpos = file_addr - sec_addr;
170
171 if (sec_addr < 0 ||
172 dpos < 0 || (dpos + sizeof (buffer)) > sizeof (sector)) {
173 sec_addr = file_addr & ~2047;
174 #ifdef USE_SCG
175 readsecs(sec_addr/2048, sector, ISO_BLOCKS(sizeof (sector)));
176 #else
177 lseek(fileno(infile), sec_addr, SEEK_SET);
178 read(fileno(infile), sector, sizeof (sector));
179 #endif
180 dpos = file_addr - sec_addr;
181 }
182 movebytes(§or[dpos], buffer, sizeof (buffer));
183 }
184
185 LOCAL void
186 showblock(flag)
187 int flag;
188 {
189 unsigned int k;
190 int i;
191 int j;
192
193 readblock();
194 if (flag) {
195 for (i = 0; i < 16; i++) {
196 crsr2(i+3, 1);
197 if (sizeof (file_addr) > sizeof (long)) {
198 printf("%16.16llx ", (Llong)file_addr+(i<<4));
199 } else {
200 printf("%8.8lx ", (long)file_addr+(i<<4));
201 }
202 for (j = 15; j >= 0; j--) {
203 printf("%2.2x", buffer[(i<<4)+j]);
204 if (!(j & 0x3))
205 printf(" ");
206 }
207 for (j = 0; j < 16; j++) {
208 k = buffer[(i << 4) + j];
209 if (k >= ' ' && k < 0x80)
210 printf("%c", k);
211 else
212 printf(".");
213 }
214 }
215 }
216 crsr2(20, 1);
217 if (sizeof (file_addr) > sizeof (long)) {
218 printf(_(" Zone, zone offset: %14llx %12.12llx "),
219 (Llong)file_addr>>11, (Llong)file_addr & 0x7ff);
220 } else {
221 printf(_(" Zone, zone offset: %6lx %4.4lx "),
222 (long)(file_addr>>11), (long)(file_addr & 0x7ff));
223 }
224 fflush(stdout);
225 }
226
227 LOCAL int
228 getbyte()
229 {
230 char c1;
231
232 c1 = buffer[file_addr & (PAGE-1)];
233 file_addr++;
234 if ((file_addr & (PAGE-1)) == 0)
235 showblock(0);
236 return (c1);
237 }
238
239 LOCAL void
240 usage(excode)
241 int excode;
242 {
243 errmsgno(EX_BAD, _("Usage: %s [options] [image]\n"),
244 get_progname());
245
246 error(_("Options:\n"));
247 error(_("\t-help, -h Print this help\n"));
248 error(_("\t-version Print version info and exit\n"));
249 error(_("\t-ignore-error Ignore errors\n"));
250 error(_("\t-i filename Filename to read ISO-9660 image from\n"));
251 error(_("\tdev=target SCSI target to use as CD/DVD-Recorder\n"));
252 error(_("\nIf neither -i nor dev= are specified, <image> is needed.\n"));
253 exit(excode);
254 }
255
256 EXPORT int
257 main(argc, argv)
258 int argc;
259 char *argv[];
260 {
261 int cac;
262 char * const *cav;
263 char *opts = "help,h,version,ignore-error,i*,dev*";
264 BOOL help = FALSE;
265 BOOL prvers = FALSE;
266 char *filename = NULL;
267 char *sdevname = NULL;
268 #if defined(USE_NLS)
269 char *dir;
270 #endif
271 char c;
272 int i;
273 int j;
274
275 save_args(argc, argv);
276
277 #if defined(USE_NLS)
278 setlocale(LC_ALL, "");
279 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
280 #define TEXT_DOMAIN "isoinfo" /* Use this only if it weren't */
281 #endif
282 dir = searchfileinpath("share/locale", F_OK,
283 SIP_ANY_FILE|SIP_NO_PATH, NULL);
284 if (dir)
285 (void) bindtextdomain(TEXT_DOMAIN, dir);
286 else
287 #if defined(PROTOTYPES) && defined(INS_BASE)
288 (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
289 #else
290 (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
291 #endif
292 (void) textdomain(TEXT_DOMAIN);
293 #endif
294
295 cac = argc - 1;
296 cav = argv + 1;
297 if (getallargs(&cac, &cav, opts, &help, &help, &prvers, &ignerr,
298 &filename, &sdevname) < 0) {
299 errmsgno(EX_BAD, _("Bad Option: '%s'\n"), cav[0]);
300 usage(EX_BAD);
301 }
302 if (help)
303 usage(0);
304 if (prvers) {
305 printf(_("devdump %s %s (%s-%s-%s) Copyright (C) 1993-1999 %s (C) 1999-2020 %s\n"),
306 VERSION,
307 VERSION_DATE,
308 HOST_CPU, HOST_VENDOR, HOST_OS,
309 _("Eric Youngdale"),
310 _("Joerg Schilling"));
311 exit(0);
312 }
313 cac = argc - 1;
314 cav = argv + 1;
315 if (filename == NULL && sdevname == NULL) {
316 if (getfiles(&cac, &cav, opts) != 0) {
317 filename = cav[0];
318 cac--, cav++;
319 }
320 }
321 if (getfiles(&cac, &cav, opts) != 0) {
322 errmsgno(EX_BAD, _("Bad Argument: '%s'\n"), cav[0]);
323 usage(EX_BAD);
324 }
325 if (filename != NULL && sdevname != NULL) {
326 errmsgno(EX_BAD, _("Only one of -i or dev= allowed\n"));
327 usage(EX_BAD);
328 }
329 #ifdef USE_SCG
330 if (filename == NULL && sdevname == NULL)
331 cdr_defaults(&sdevname, NULL, NULL, NULL, NULL);
332 #endif
333 if (filename == NULL && sdevname == NULL) {
334 fprintf(stderr, _("ISO-9660 image not specified\n"));
335 usage(EX_BAD);
336 }
337
338 if (filename != NULL)
339 infile = fopen(filename, "rb");
340 else
341 filename = sdevname;
342
343 if (infile != NULL) {
344 /* EMPTY */;
345 #ifdef USE_SCG
346 } else if (scsidev_open(filename) < 0) {
347 #else
348 } else {
349 #endif
350 fprintf(stderr, _("Cannot open '%s'\n"), filename);
351 exit(1);
352 }
353
354 for (i = 0; i < 30; i++)
355 printf("\n");
356 file_addr = (off_t)0;
357
358 /*
359 * Now setup the keyboard for single character input.
360 */
361 #ifdef USE_V7_TTY
362 if (ioctl(STDIN_FILENO, TIOCGETP, &savetty) == -1) {
363 #else
364 #ifdef USE_TERMIOS
365 #ifdef TCSANOW
366 if (tcgetattr(STDIN_FILENO, &savetty) == -1) {
367 #else
368 if (ioctl(STDIN_FILENO, TCGETA, &savetty) == -1) {
369 #endif
370 #else /* USE_TERMIOS */
371 if (0) {
372 #endif /* USE_TERMIOS */
373 #endif
374 printf(_("Stdin must be a tty\n"));
375 exit(1);
376 }
377 #ifdef USE_V7_TTY
378 newtty = savetty;
379 newtty.sg_flags &= ~(ECHO|CRMOD);
380 newtty.sg_flags |= CBREAK;
381 #else
382 #ifdef USE_TERMIOS
383 newtty = savetty;
384 newtty.c_lflag &= ~ICANON;
385 newtty.c_lflag &= ~ECHO;
386 newtty.c_cc[VMIN] = 1;
387 #endif
388 #endif
389 set_tty();
390 #ifdef SIGTSTP
391 signal(SIGTSTP, onsusp);
392 #endif
393 on_comerr((void(*)__PR((int, void *)))reset_tty, NULL);
394
395 do {
396 if (file_addr < (off_t)0) file_addr = (off_t)0;
397 showblock(1);
398 #ifdef USE_GETCH
399 c = getch(); /* DOS console input */
400 #else
401 read(STDIN_FILENO, &c, 1);
402 #endif
403 if (c == 'a')
404 file_addr -= PAGE;
405 if (c == 'b')
406 file_addr += PAGE;
407 if (c == 'g') {
408 crsr2(20, 1);
409 printf(_("Enter new starting block (in hex):"));
410 if (sizeof (file_addr) > sizeof (long)) {
411 Llong ll;
412 scanf("%llx", &ll);
413 file_addr = (off_t)ll;
414 } else {
415 long l;
416 scanf("%lx", &l);
417 file_addr = (off_t)l;
418 }
419 file_addr = file_addr << 11;
420 crsr2(20, 1);
421 printf(" ");
422 }
423 if (c == 'f') {
424 crsr2(20, 1);
425 printf(_("Enter new search string:"));
426 fgets((char *)search, sizeof (search), stdin);
427 while (search[strlen((char *)search)-1] == '\n')
428 search[strlen((char *)search)-1] = 0;
429 crsr2(20, 1);
430 printf(" ");
431 }
432 if (c == '+') {
433 while (1 == 1) {
434 int slen;
435
436 while (1 == 1) {
437 c = getbyte();
438 if (c == search[0])
439 break;
440 }
441 slen = (int)strlen((char *)search);
442 for (j = 1; j < slen; j++) {
443 if (search[j] != getbyte())
444 break;
445 }
446 if (j == slen)
447 break;
448 }
449 file_addr &= ~(PAGE-1);
450 showblock(1);
451 }
452 if (c == 'q')
453 break;
454 } while (1 == 1);
455 reset_tty();
456 if (infile != NULL)
457 fclose(infile);
458 return (0);
459 }
460