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(&sector[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