1 /* @(#)isodump.c 1.53 20/05/05 joerg */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)isodump.c 1.53 20/05/05 joerg";
6 #endif
7 /*
8 * File isodump.c - dump iso9660 directory information.
9 *
10 *
11 * Written by Eric Youngdale (1993).
12 *
13 * Copyright 1993 Yggdrasil Computing, Incorporated
14 * Copyright (c) 1999-2020 J. Schilling
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License version 2
18 * as published by the Free Software Foundation.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License along with
26 * this program; see the file COPYING. If not, write to the Free Software
27 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 */
29
30 #include <schily/stdlib.h>
31 #include <schily/unistd.h>
32 #include <schily/string.h>
33 #include <schily/utypes.h>
34
35 #include <schily/stdio.h>
36 #include <schily/standard.h>
37 #include <schily/termios.h>
38 #include <schily/signal.h>
39 #include <schily/schily.h>
40 #include <schily/nlsdefs.h>
41
42 #include "../iso9660.h"
43 #include "../rock.h"
44 #include "../scsi.h"
45 #include "cdrdeflt.h"
46 #include "../../cdrecord/version.h"
47
48 /*
49 * XXX JS: Some structures have odd lengths!
50 * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length.
51 * For this reason, we cannot use sizeof (struct iso_path_table) or
52 * sizeof (struct iso_directory_record) to compute on disk sizes.
53 * Instead, we use offsetof(..., name) and add the name size.
54 * See iso9660.h
55 */
56 #ifndef offsetof
57 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
58 #endif
59
60 /*
61 * Note: always use these macros to avoid problems.
62 *
63 * ISO_ROUND_UP(X) may cause an integer overflow and thus give
64 * incorrect results. So avoid it if possible.
65 *
66 * ISO_BLOCKS(X) is overflow safe. Prefer this when ever it is possible.
67 */
68 #define SECTOR_SIZE (2048)
69 #define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
70 #define ISO_BLOCKS(X) (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
71
72 #define infile in_image
73 EXPORT FILE *infile = NULL;
74 EXPORT BOOL ignerr = FALSE;
75 LOCAL off_t file_addr;
76 LOCAL int su_version;
77 LOCAL int rr_version;
78 LOCAL int use_rock = TRUE;
79 LOCAL unsigned char buffer[2048];
80 LOCAL unsigned char search[64];
81 LOCAL int blocksize;
82
83 #define PAGE sizeof (buffer)
84
85 LOCAL int isonum_731 __PR((char * p));
86 LOCAL int isonum_721 __PR((char * p));
87 LOCAL int isonum_723 __PR((char * p));
88 LOCAL int isonum_733 __PR((char * p));
89 LOCAL void reset_tty __PR((void));
90 LOCAL void set_tty __PR((void));
91 LOCAL void onsusp __PR((int signo));
92 LOCAL void crsr2 __PR((int row, int col));
93 LOCAL int parse_rr __PR((unsigned char * pnt, int len, int cont_flag));
94 LOCAL void find_rr __PR((struct iso_directory_record * idr, Uchar **pntp, int *lenp));
95 LOCAL int dump_rr __PR((struct iso_directory_record * idr));
96 LOCAL void showblock __PR((int flag));
97 LOCAL int getbyte __PR((void));
98 LOCAL void usage __PR((int excode));
99 EXPORT int main __PR((int argc, char *argv[]));
100
101 LOCAL int
isonum_731(p)102 isonum_731(p)
103 char *p;
104 {
105 return ((p[0] & 0xff)
106 | ((p[1] & 0xff) << 8)
107 | ((p[2] & 0xff) << 16)
108 | ((p[3] & 0xff) << 24));
109 }
110
111 LOCAL int
isonum_721(p)112 isonum_721(p)
113 char *p;
114 {
115 return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
116 }
117
118 LOCAL int
isonum_723(p)119 isonum_723(p)
120 char *p;
121 {
122 #if 0
123 if (p[0] != p[3] || p[1] != p[2]) {
124 fprintf(stderr, "invalid format 7.2.3 number\n");
125 exit(1);
126 }
127 #endif
128 return (isonum_721(p));
129 }
130
131
132 LOCAL int
isonum_733(p)133 isonum_733(p)
134 char *p;
135 {
136 return (isonum_731(p));
137 }
138
139 #ifdef USE_V7_TTY
140 LOCAL struct sgttyb savetty;
141 LOCAL struct sgttyb newtty;
142 #else
143 #ifdef USE_TERMIOS
144 LOCAL struct termios savetty;
145 LOCAL struct termios newtty;
146 #endif
147 #endif
148
149 LOCAL void
reset_tty()150 reset_tty()
151 {
152 #ifdef USE_V7_TTY
153 if (ioctl(STDIN_FILENO, TIOCSETN, &savetty) == -1) {
154 #else
155 #ifdef USE_TERMIOS
156 #ifdef TCSANOW
157 if (tcsetattr(STDIN_FILENO, TCSANOW, &savetty) == -1) {
158 #else
159 if (ioctl(STDIN_FILENO, TCSETAF, &savetty) == -1) {
160 #endif
161 #else /* USE_TERMIOS */
162 if (0) {
163 #endif /* USE_TERMIOS */
164 #endif
165 printf(_("Cannot put tty into normal mode\n"));
166 exit(1);
167 }
168 }
169
170 LOCAL void
171 set_tty()
172 {
173 #ifdef USE_V7_TTY
174 if (ioctl(STDIN_FILENO, TIOCSETN, &newtty) == -1) {
175 #else
176 #ifdef USE_TERMIOS
177 #ifdef TCSANOW
178 if (tcsetattr(STDIN_FILENO, TCSANOW, &newtty) == -1) {
179 #else
180 if (ioctl(STDIN_FILENO, TCSETAF, &newtty) == -1) {
181 #endif
182 #else /* USE_TERMIOS */
183 if (0) {
184 #endif /* USE_TERMIOS */
185 #endif
186 printf(_("Cannot put tty into raw mode\n"));
187 exit(1);
188 }
189 }
190
191 /* Come here when we get a suspend signal from the terminal */
192
193 LOCAL void
194 onsusp(signo)
195 int signo;
196 {
197 #ifdef SIGTTOU
198 /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
199 signal(SIGTTOU, SIG_IGN);
200 #endif
201 reset_tty();
202 fflush(stdout);
203 #ifdef SIGTTOU
204 signal(SIGTTOU, SIG_DFL);
205 /* Send the TSTP signal to suspend our process group */
206 signal(SIGTSTP, SIG_DFL);
207 /* sigsetmask(0);*/
208 kill(0, SIGTSTP);
209 /* Pause for station break */
210
211 /* We're back */
212 signal(SIGTSTP, onsusp);
213 #endif
214 set_tty();
215 }
216
217
218
219 LOCAL void
220 crsr2(row, col)
221 int row;
222 int col;
223 {
224 printf("\033[%d;%dH", row, col);
225 }
226
227 LOCAL int
228 parse_rr(pnt, len, cont_flag)
229 unsigned char *pnt;
230 int len;
231 int cont_flag;
232 {
233 int slen;
234 int ncount;
235 int extent;
236 off_t cont_extent;
237 int cont_offset;
238 int cont_size;
239 int flag1;
240 int flag2;
241 unsigned char *pnts;
242 char symlinkname[1024];
243 char name[1024];
244 int goof = 0;
245
246 /* printf(" RRlen=%d ", len); */
247
248 symlinkname[0] = 0;
249
250 cont_extent = (off_t)0;
251 cont_offset = cont_size = 0;
252
253 ncount = 0;
254 flag1 = -1;
255 flag2 = 0;
256 while (len >= 4) {
257 if (ncount)
258 printf(",");
259 else
260 printf("[");
261 printf("%c%c", pnt[0], pnt[1]);
262 if (pnt[3] != 1 && pnt[3] != 2) {
263 printf(_("**BAD RRVERSION (%d) for %c%c\n"), pnt[3], pnt[0], pnt[1]);
264 return (0); /* JS ??? Is this right ??? */
265 } else if (pnt[2] < 4) {
266 printf(_("**BAD RRLEN (%d) in '%2.2s' field %2.2X %2.2X.\n"), pnt[2], pnt, pnt[0], pnt[1]);
267 return (0); /* JS ??? Is this right ??? */
268 } else if (pnt[0] == 'R' && pnt[1] == 'R') {
269 printf("=%d", pnt[3]); /* RR version */
270 }
271 ncount++;
272 if (pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
273 if (strncmp((char *)pnt, "PX", 2) == 0) flag2 |= RR_FLAG_PX;
274 if (strncmp((char *)pnt, "PN", 2) == 0) flag2 |= RR_FLAG_PN;
275 if (strncmp((char *)pnt, "SL", 2) == 0) flag2 |= RR_FLAG_SL;
276 if (strncmp((char *)pnt, "NM", 2) == 0) {
277 slen = pnt[2] - 5;
278 pnts = pnt+5;
279 if ((pnt[4] & 6) != 0) {
280 printf("*");
281 }
282 memset(name, 0, sizeof (name));
283 memcpy(name, pnts, slen);
284 printf("=%s", name);
285 flag2 |= RR_FLAG_NM;
286 }
287 if (strncmp((char *)pnt, "CL", 2) == 0) flag2 |= RR_FLAG_CL;
288 if (strncmp((char *)pnt, "PL", 2) == 0) flag2 |= RR_FLAG_PL;
289 if (strncmp((char *)pnt, "RE", 2) == 0) flag2 |= RR_FLAG_RE;
290 if (strncmp((char *)pnt, "TF", 2) == 0) flag2 |= RR_FLAG_TF;
291
292 if (strncmp((char *)pnt, "PX", 2) == 0) {
293 extent = isonum_733((char *)pnt+12); /* Link count */
294 printf("=%x", extent);
295 }
296
297 if (strncmp((char *)pnt, "CE", 2) == 0) {
298 cont_extent = (off_t)isonum_733((char *)pnt+4);
299 cont_offset = isonum_733((char *)pnt+12);
300 cont_size = isonum_733((char *)pnt+20);
301 printf("=[%x,%x,%d]", (int)cont_extent, cont_offset,
302 cont_size);
303 }
304
305 if (strncmp((char *)pnt, "ER", 2) == 0) { /* ER */
306 int lid = pnt[4] & 0xFF; /* Len ID */
307 int ldes = pnt[5] & 0xFF; /* Len des */
308 int lsrc = pnt[6] & 0xFF; /* Len src */
309 int xver = pnt[7] & 0xFF; /* X vers */
310 flag2 |= RR_FLAG_ER; /* ER record */
311
312 rr_version = xver;
313 printf(_("=[len_id=%d,len_des=%d,len_src=%d,ext_ver=%d,id=\"%.*s\"]"),
314 lid, ldes, lsrc, xver, lid, &pnt[8]);
315
316 }
317 if (strncmp((char *)pnt, "SP", 2) == 0) { /* SUSP */
318 flag2 |= RR_FLAG_SP; /* SUSP record */
319 su_version = pnt[3] & 0xff;
320 printf(_("=[skip=%d]"), pnt[6] & 0xFF); /* SUSP skip off */
321
322 }
323 if (strncmp((char *)pnt, "ST", 2) == 0) { /* Terminate SUSP */
324 break;
325 }
326
327 if (strncmp((char *)pnt, "PL", 2) == 0 || strncmp((char *)pnt, "CL", 2) == 0) {
328 extent = isonum_733((char *)pnt+4);
329 printf("=%x", extent); /* DIR extent */
330 }
331
332 if (strncmp((char *)pnt, "SL", 2) == 0) {
333 int cflag;
334
335 cflag = pnt[4]; /* Component flag */
336 pnts = pnt+5;
337 slen = pnt[2] - 5;
338 while (slen >= 1) {
339 switch (pnts[0] & 0xfe) {
340 case 0:
341 strncat(symlinkname, (char *)(pnts+2), pnts[1]);
342 break;
343 case 2:
344 strcat(symlinkname, ".");
345 break;
346 case 4:
347 strcat(symlinkname, "..");
348 break;
349 case 8:
350 if ((pnts[0] & 1) == 0)
351 strcat(symlinkname, "/");
352 break;
353 case 16:
354 strcat(symlinkname, "/mnt");
355 printf(_("Warning - mount point requested"));
356 break;
357 case 32:
358 strcat(symlinkname, "kafka");
359 printf(_("Warning - host_name requested"));
360 break;
361 default:
362 printf(_("Reserved bit setting in symlink"));
363 goof++;
364 break;
365 }
366 if ((pnts[0] & 0xfe) && pnts[1] != 0) {
367 printf(_("Incorrect length in symlink component"));
368 }
369 if ((pnts[0] & 1) == 0)
370 strcat(symlinkname, "/");
371
372 slen -= (pnts[1] + 2);
373 pnts += (pnts[1] + 2);
374 }
375 if (cflag)
376 strcat(symlinkname, "+");
377 printf("=%s", symlinkname);
378 symlinkname[0] = 0;
379 }
380
381 len -= pnt[2];
382 pnt += pnt[2];
383 }
384 if (cont_extent) {
385 unsigned char sector[2048];
386
387 #ifdef USE_SCG
388 readsecs(cont_extent * blocksize / 2048, sector, ISO_BLOCKS(sizeof (sector)));
389 #else
390 lseek(fileno(infile), cont_extent * blocksize, SEEK_SET);
391 read(fileno(infile), sector, sizeof (sector));
392 #endif
393 flag2 |= parse_rr(§or[cont_offset], cont_size, 1);
394 }
395 if (ncount)
396 printf("]");
397 if (!cont_flag && flag1 != -1 && flag1 != (flag2 & 0xFF)) {
398 printf(_("Flag %x != %x"), flag1, flag2);
399 goof++;
400 }
401 /*
402 * XXX Check goof?
403 */
404 return (flag2);
405 }
406
407 LOCAL void
408 find_rr(idr, pntp, lenp)
409 struct iso_directory_record *idr;
410 Uchar **pntp;
411 int *lenp;
412 {
413 struct iso_xa_dir_record *xadp;
414 int len;
415 unsigned char * pnt;
416
417 len = idr->length[0] & 0xff;
418 len -= offsetof(struct iso_directory_record, name[0]);
419 len -= idr->name_len[0];
420
421 pnt = (unsigned char *) idr;
422 pnt += offsetof(struct iso_directory_record, name[0]);
423 pnt += idr->name_len[0];
424 if ((idr->name_len[0] & 1) == 0) {
425 pnt++;
426 len--;
427 }
428 if (len >= 14) {
429 xadp = (struct iso_xa_dir_record *)pnt;
430
431 if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' &&
432 xadp->reserved[0] == '\0') {
433 len -= 14;
434 pnt += 14;
435 }
436 }
437 *pntp = pnt;
438 *lenp = len;
439 }
440
441 LOCAL int
442 dump_rr(idr)
443 struct iso_directory_record *idr;
444 {
445 int len;
446 unsigned char *pnt;
447
448 find_rr(idr, &pnt, &len);
449 return (parse_rr(pnt, len, 0));
450 }
451
452
453 LOCAL void
454 showblock(flag)
455 int flag;
456 {
457 int i;
458 int j;
459 int line;
460 struct iso_directory_record *idr;
461
462 #ifdef USE_SCG
463 readsecs(file_addr / 2048, buffer, ISO_BLOCKS(sizeof (buffer)));
464 #else
465 lseek(fileno(infile), file_addr, SEEK_SET);
466 read(fileno(infile), buffer, sizeof (buffer));
467 #endif
468 for (i = 0; i < 60; i++)
469 printf("\n");
470 fflush(stdout);
471 i = line = 0;
472 if (flag) {
473 while (1 == 1) {
474 crsr2(line+3, 1);
475 idr = (struct iso_directory_record *) &buffer[i];
476 if (idr->length[0] == 0)
477 break;
478 printf("%3d ", idr->length[0]);
479 printf("[%2d] ", idr->volume_sequence_number[0]);
480 printf("%5x ", isonum_733(idr->extent));
481 printf("%8d ", isonum_733(idr->size));
482 printf("%02x/", idr->flags[0]);
483 printf((idr->flags[0] & 2) ? "*" : " ");
484 if (idr->name_len[0] == 1 && idr->name[0] == 0)
485 printf(". ");
486 else if (idr->name_len[0] == 1 && idr->name[0] == 1)
487 printf(".. ");
488 else {
489 for (j = 0; j < (int)idr->name_len[0]; j++) printf("%c", idr->name[j]);
490 for (j = 0; j < (14 - (int)idr->name_len[0]); j++) printf(" ");
491 }
492 if (use_rock)
493 dump_rr(idr);
494 printf("\n");
495 i += buffer[i];
496 if (i > 2048 - offsetof(struct iso_directory_record, name[0]))
497 break;
498 line++;
499 }
500 }
501 printf("\n");
502 if (sizeof (file_addr) > sizeof (long)) {
503 printf(_(" Zone, zone offset: %14llx %12.12llx "),
504 (Llong)file_addr / blocksize,
505 (Llong)file_addr & (Llong)(blocksize - 1));
506 } else {
507 printf(_(" Zone, zone offset: %6lx %4.4lx "),
508 (long) (file_addr / blocksize),
509 (long) file_addr & (blocksize - 1));
510 }
511 fflush(stdout);
512 }
513
514 LOCAL int
515 getbyte()
516 {
517 char c1;
518
519 c1 = buffer[file_addr & (blocksize-1)];
520 file_addr++;
521 if ((file_addr & (blocksize-1)) == 0)
522 showblock(0);
523 return (c1);
524 }
525
526 LOCAL void
527 usage(excode)
528 int excode;
529 {
530 errmsgno(EX_BAD, _("Usage: %s [options] image\n"),
531 get_progname());
532
533 error(_("Options:\n"));
534 error(_("\t-help, -h Print this help\n"));
535 error(_("\t-version Print version info and exit\n"));
536 error(_("\t-ignore-error Ignore errors\n"));
537 error(_("\t-i filename Filename to read ISO-9660 image from\n"));
538 error(_("\tdev=target SCSI target to use as CD/DVD-Recorder\n"));
539 error(_("\nIf neither -i nor dev= are specified, <image> is needed.\n"));
540 exit(excode);
541 }
542
543 EXPORT int
544 main(argc, argv)
545 int argc;
546 char *argv[];
547 {
548 int cac;
549 char * const *cav;
550 char *opts = "help,h,version,ignore-error,i*,dev*";
551 BOOL help = FALSE;
552 BOOL prvers = FALSE;
553 char *filename = NULL;
554 char *sdevname = NULL;
555 #if defined(USE_NLS)
556 char *dir;
557 #endif
558 char c;
559 int i;
560 struct iso_primary_descriptor ipd;
561 struct iso_directory_record *idr;
562
563 save_args(argc, argv);
564
565 #if defined(USE_NLS)
566 setlocale(LC_ALL, "");
567 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
568 #define TEXT_DOMAIN "isoinfo" /* Use this only if it weren't */
569 #endif
570 dir = searchfileinpath("share/locale", F_OK,
571 SIP_ANY_FILE|SIP_NO_PATH, NULL);
572 if (dir)
573 (void) bindtextdomain(TEXT_DOMAIN, dir);
574 else
575 #if defined(PROTOTYPES) && defined(INS_BASE)
576 (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
577 #else
578 (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
579 #endif
580 (void) textdomain(TEXT_DOMAIN);
581 #endif
582
583 cac = argc - 1;
584 cav = argv + 1;
585 if (getallargs(&cac, &cav, opts, &help, &help, &prvers, &ignerr,
586 &filename, &sdevname) < 0) {
587 errmsgno(EX_BAD, _("Bad Option: '%s'\n"), cav[0]);
588 usage(EX_BAD);
589 }
590 if (help)
591 usage(0);
592 if (prvers) {
593 printf(_("isodump %s %s (%s-%s-%s) Copyright (C) 1993-1999 %s (C) 1999-2020 %s\n"),
594 VERSION,
595 VERSION_DATE,
596 HOST_CPU, HOST_VENDOR, HOST_OS,
597 _("Eric Youngdale"),
598 _("Joerg Schilling"));
599 exit(0);
600 }
601 cac = argc - 1;
602 cav = argv + 1;
603 if (filename == NULL && sdevname == NULL) {
604 if (getfiles(&cac, &cav, opts) != 0) {
605 filename = cav[0];
606 cac--, cav++;
607 }
608 }
609 if (getfiles(&cac, &cav, opts) != 0) {
610 errmsgno(EX_BAD, _("Bad Argument: '%s'\n"), cav[0]);
611 usage(EX_BAD);
612 }
613 if (filename != NULL && sdevname != NULL) {
614 errmsgno(EX_BAD, _("Only one of -i or dev= allowed\n"));
615 usage(EX_BAD);
616 }
617 #ifdef USE_SCG
618 if (filename == NULL && sdevname == NULL)
619 cdr_defaults(&sdevname, NULL, NULL, NULL, NULL);
620 #endif
621 if (filename == NULL && sdevname == NULL) {
622 fprintf(stderr, _("ISO-9660 image not specified\n"));
623 usage(EX_BAD);
624 }
625
626 if (filename != NULL)
627 infile = fopen(filename, "rb");
628 else
629 filename = sdevname;
630
631 if (infile != NULL) {
632 /* EMPTY */;
633 #ifdef USE_SCG
634 } else if (scsidev_open(filename) < 0) {
635 #else
636 } else {
637 #endif
638 fprintf(stderr, _("Cannot open '%s'\n"), filename);
639 exit(1);
640 }
641
642 file_addr = (off_t) (16 << 11);
643 #ifdef USE_SCG
644 readsecs(file_addr / 2048, &ipd, ISO_BLOCKS(sizeof (ipd)));
645 #else
646 lseek(fileno(infile), file_addr, SEEK_SET);
647 read(fileno(infile), &ipd, sizeof (ipd));
648 #endif
649 idr = (struct iso_directory_record *)ipd.root_directory_record;
650
651 blocksize = isonum_723((char *)ipd.logical_block_size);
652 if (blocksize != 512 && blocksize != 1024 && blocksize != 2048) {
653 blocksize = 2048;
654 }
655
656 file_addr = (off_t)isonum_733(idr->extent);
657 file_addr = file_addr * blocksize;
658
659 #ifdef USE_SCG
660 readsecs(file_addr / 2048, buffer, ISO_BLOCKS(sizeof (buffer)));
661 #else
662 lseek(fileno(infile), file_addr, SEEK_SET);
663 read(fileno(infile), buffer, sizeof (buffer));
664 #endif
665 i = dump_rr((struct iso_directory_record *) buffer);
666 if (i == 0 ||
667 (i & (RR_FLAG_SP | RR_FLAG_ER)) == 0 || su_version < 1 || rr_version < 1) {
668 use_rock = FALSE;
669 }
670
671 /* Now setup the keyboard for single character input. */
672 #ifdef USE_V7_TTY
673 if (ioctl(STDIN_FILENO, TIOCGETP, &savetty) == -1) {
674 #else
675 #ifdef USE_TERMIOS
676 #ifdef TCSANOW
677 if (tcgetattr(STDIN_FILENO, &savetty) == -1) {
678 #else
679 if (ioctl(STDIN_FILENO, TCGETA, &savetty) == -1) {
680 #endif
681 #else /* USE_TERMIOS */
682 if (0) {
683 #endif /* USE_TERMIOS */
684 #endif
685 printf(_("Stdin must be a tty\n"));
686 exit(1);
687 }
688 #ifdef USE_V7_TTY
689 newtty = savetty;
690 newtty.sg_flags &= ~(ECHO|CRMOD);
691 newtty.sg_flags |= CBREAK;
692 #else
693 #ifdef USE_TERMIOS
694 newtty = savetty;
695 newtty.c_lflag &= ~ICANON;
696 newtty.c_lflag &= ~ECHO;
697 newtty.c_cc[VMIN] = 1;
698 #endif
699 #endif
700 set_tty();
701 #ifdef SIGTSTP
702 signal(SIGTSTP, onsusp);
703 #endif
704 on_comerr((void(*)__PR((int, void *)))reset_tty, NULL);
705
706 do {
707 if (file_addr < 0)
708 file_addr = (off_t)0;
709 showblock(1);
710 #ifdef USE_GETCH
711 c = getch(); /* DOS console input */
712 #else
713 read(STDIN_FILENO, &c, 1);
714 #endif
715 if (c == 'a')
716 file_addr -= blocksize;
717 if (c == 'b')
718 file_addr += blocksize;
719 if (c == 'g') {
720 crsr2(20, 1);
721 printf(_("Enter new starting block (in hex):"));
722 if (sizeof (file_addr) > sizeof (long)) {
723 Llong ll;
724 scanf("%llx", &ll);
725 file_addr = (off_t)ll;
726 } else {
727 long l;
728 scanf("%lx", &l);
729 file_addr = (off_t)l;
730 }
731 file_addr = file_addr * blocksize;
732 crsr2(20, 1);
733 printf(" ");
734 }
735 if (c == 'f') {
736 crsr2(20, 1);
737 printf(_("Enter new search string:"));
738 fgets((char *)search, sizeof (search), stdin);
739 while (search[strlen((char *)search)-1] == '\n')
740 search[strlen((char *)search)-1] = 0;
741 crsr2(20, 1);
742 printf(" ");
743 }
744 if (c == '+') {
745 while (1 == 1) {
746 int slen;
747
748 while (1 == 1) {
749 c = getbyte();
750 if (c == search[0])
751 break;
752 }
753 slen = (int)strlen((char *)search);
754 for (i = 1; i < slen; i++) {
755 if (search[i] != getbyte())
756 break;
757 }
758 if (i == slen)
759 break;
760 }
761 file_addr &= ~(blocksize-1);
762 showblock(1);
763 }
764 if (c == 'q')
765 break;
766 } while (1 == 1);
767 reset_tty();
768 if (infile != NULL)
769 fclose(infile);
770 return (0);
771 }
772