source: trunk/minix/commands/de/de_stdout.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 25.3 KB
Line 
1/****************************************************************/
2/* */
3/* de_stdout.c */
4/* */
5/* Displaying information from the "Disk editor". */
6/* */
7/****************************************************************/
8/* origination 1989-Jan-15 Terrence W. Holm */
9/****************************************************************/
10
11
12#include <minix/config.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <fcntl.h>
16#include <limits.h>
17#include <grp.h>
18#include <pwd.h>
19#include <stdarg.h>
20#include <stdlib.h>
21#include <string.h>
22#include <termcap.h>
23#include <time.h>
24#include <unistd.h>
25
26#include <minix/const.h>
27#include <minix/type.h>
28#include "../../servers/fs/const.h"
29#include "../../servers/fs/type.h"
30#include "../../servers/fs/inode.h"
31#include <minix/fslib.h>
32
33#include "de.h"
34
35#ifndef major
36#define major(x) ( (x>>8) & 0377)
37#define minor(x) (x & 0377)
38#endif
39
40/****************************************************************/
41/* Code for handling termcap */
42/****************************************************************/
43
44
45#define TC_BUFFER 1024 /* Size of termcap(3) buffer */
46#define TC_STRINGS 200 /* Enough room for cm,cl,so,se */
47
48
49static char *Tmove; /* (cm) - Format for tgoto */
50static char *Tclr_all; /* (cl) - Clear screen */
51static char *Treverse; /* (so) - Start reverse mode */
52static char *Tnormal; /* (se) - End reverse mode */
53
54char Kup = 0; /* (ku) - Up arrow key */
55char Kdown = 0; /* (kd) - Down arrow key */
56char Kleft = 0; /* (kl) - Left arrow key */
57char Kright = 0; /* (kr) - Right arrow key */
58
59_PROTOTYPE(void Goto , (int column , int line ));
60_PROTOTYPE(void Block_Type , (de_state *s ));
61_PROTOTYPE(void Draw_Words , (de_state *s ));
62_PROTOTYPE(void Draw_Info , (de_state *s ));
63_PROTOTYPE(void Draw_Block , (char *block ));
64_PROTOTYPE(void Draw_Map , (char *block , int max_bits ));
65_PROTOTYPE(void Draw_Offset , (de_state *s ));
66_PROTOTYPE(void Word_Pointers , (off_t old_addr , off_t new_addr ));
67_PROTOTYPE(void Block_Pointers , (off_t old_addr , off_t new_addr ));
68_PROTOTYPE(void Map_Pointers , (off_t old_addr , off_t new_addr ));
69_PROTOTYPE(void Print_Number , (Word_t number , int output_base ));
70_PROTOTYPE(void Draw_Zone_Numbers , (de_state *s , struct inode *inode ,
71 int zindex , int zrow ));
72
73
74
75/****************************************************************/
76/* */
77/* Init_Termcap() */
78/* */
79/* Initializes the external variables for the */
80/* current terminal. */
81/* */
82/****************************************************************/
83
84
85int Init_Termcap()
86
87 {
88 char *term;
89 char buffer[ TC_BUFFER ];
90 static char strings[ TC_STRINGS ];
91 char *s = &strings[0];
92 char *Kcode;
93
94
95 term = getenv( "TERM" );
96
97 if ( term == NULL )
98 return( 0 );
99
100 if ( tgetent( buffer, term ) != 1 )
101 return( 0 );
102
103
104 if ( (Tmove = tgetstr( "cm", &s )) == NULL )
105 return( 0 );
106
107 if ( (Tclr_all = tgetstr( "cl", &s )) == NULL )
108 return( 0 );
109
110 if ( (Treverse = tgetstr( "so", &s )) == NULL )
111 {
112 Treverse = Tnormal = s;
113 *s = '\0';
114 ++s;
115 }
116 else if ( (Tnormal = tgetstr( "se", &s )) == NULL )
117 return( 0 );
118
119
120 /* See if there are single character arrow key codes */
121
122 if ( (Kcode = tgetstr( "ku", &s )) != NULL && strlen( Kcode ) == 1 )
123 Kup = Kcode[0];
124
125 if ( (Kcode = tgetstr( "kd", &s )) != NULL && strlen( Kcode ) == 1 )
126 Kdown = Kcode[0];
127
128 if ( (Kcode = tgetstr( "kl", &s )) != NULL && strlen( Kcode ) == 1 )
129 Kleft = Kcode[0];
130
131 if ( (Kcode = tgetstr( "kr", &s )) != NULL && strlen( Kcode ) == 1 )
132 Kright = Kcode[0];
133
134
135 return( 1 );
136 }
137
138
139
140
141
142
143/****************************************************************/
144/* */
145/* Goto( column, line ) */
146/* */
147/* Use the termcap string to move the cursor. */
148/* */
149/****************************************************************/
150
151
152void Goto( column, line )
153 int column;
154 int line;
155
156 {
157 fputs( tgoto( Tmove, column, line ), stdout );
158 }
159
160
161
162
163
164
165/****************************************************************/
166/* Output routines */
167/****************************************************************/
168
169
170
171
172/****************************************************************/
173/* */
174/* Draw_Help_Screen() */
175/* */
176/****************************************************************/
177
178
179void Draw_Help_Screen( s )
180 de_state *s;
181
182 {
183 int down;
184 int right;
185
186 switch ( s->mode )
187 {
188 case WORD : down = 2; right = 32; break;
189 case BLOCK : down = 64; right = 1; break;
190 case MAP : down = 256; right = 4; break;
191 }
192
193 printf( "%s ", Tclr_all );
194 printf( "%sDE COMMANDS%s\r\n\n\n", Treverse, Tnormal );
195
196
197 printf( " PGUP b Back one block h Help\r\n" );
198 printf( " PGDN f Forward one block q Quit\r\n" );
199 printf( " HOME B Goto first block m Minix shell\r\n" );
200 printf( " END F Goto last block\r\n" );
201 printf( " v Visual mode (w b m)\r\n" );
202 printf( " g Goto specified block o Output base (h d o b)\r\n" );
203 printf( " G Goto block indirectly\r\n" );
204 printf( " i Goto i-node c Change file name\r\n" );
205 printf( " I Filename to i-node w Write ASCII block\r\n" );
206 printf( " W Write block exactly\r\n" );
207 printf( " / Search\r\n" );
208 printf( " n Next occurrence x Extract lost entry\r\n" );
209 printf( " p Previous address X Extract lost blocks\r\n" );
210 printf( " s Store word\r\n" );
211 printf( " UP u Move back %d bytes\r\n", down );
212 printf( " DOWN d Move forward %d bytes\r\n", down );
213 printf( " LEFT l Move back %d byte%s\r\n", right,
214 right == 1 ? "" : "s" );
215 printf( " RIGHT r Move forward %d byte%s\r\n\n\n", right,
216 right == 1 ? "" : "s" );
217 }
218
219
220
221
222
223
224/****************************************************************/
225/* */
226/* Wait_For_Key() */
227/* */
228/* The user must press a key to continue. */
229/* */
230/****************************************************************/
231
232
233void Wait_For_Key()
234
235 {
236 Draw_Prompt( "Press a key to continue..." );
237
238 Get_Char();
239 }
240
241
242
243
244
245
246/****************************************************************/
247/* */
248/* Draw_Prompt( string ) */
249/* */
250/* Write a message in the "prompt" area. */
251/* */
252/****************************************************************/
253
254
255void Draw_Prompt( string )
256 char *string;
257
258 {
259 Goto( PROMPT_COLUMN, PROMPT_LINE );
260
261 printf( "%s%s%s ", Treverse, string, Tnormal );
262 }
263
264
265
266
267
268
269/****************************************************************/
270/* */
271/* Erase_Prompt() */
272/* */
273/* Erase the message in the "prompt" area. */
274/* */
275/****************************************************************/
276
277
278void Erase_Prompt()
279
280 {
281 Goto( PROMPT_COLUMN, PROMPT_LINE );
282
283 printf( "%77c", ' ' );
284
285 Goto( PROMPT_COLUMN, PROMPT_LINE );
286 }
287
288
289
290
291
292
293/****************************************************************/
294/* */
295/* Draw_Screen( state ) */
296/* */
297/* Redraw everything, except pointers. */
298/* */
299/****************************************************************/
300
301
302void Draw_Screen( s )
303 de_state *s;
304
305 {
306 fputs( Tclr_all, stdout );
307
308 Draw_Strings( s );
309 Block_Type( s );
310
311 switch ( s->mode )
312 {
313 case WORD : Draw_Words( s );
314 Draw_Info( s );
315 break;
316
317 case BLOCK : Draw_Block( s->buffer );
318 break;
319
320 case MAP : {
321 int max_bits = 2 * K;
322
323 /* Don't display the bits after the end */
324 /* of the i-node or zone bit maps. */
325
326 if ( s->block == 2 + s->inode_maps - 1 )
327 max_bits = (int)
328 (s->inodes_in_map
329 - CHAR_BIT * K * (ino_t) (s->inode_maps - 1)
330 - CHAR_BIT * (ino_t) (s->offset & ~ MAP_MASK));
331
332 else if ( s->block == 2 + s->inode_maps + s->zone_maps - 1 )
333 max_bits = (int)
334 (s->zones_in_map
335 - CHAR_BIT * K * (zone_t) (s->zone_maps - 1)
336 - CHAR_BIT * (zone_t) (s->offset & ~ MAP_MASK));
337
338 if ( max_bits < 0 )
339 max_bits = 0;
340
341 Draw_Map( &s->buffer[ s->offset & ~ MAP_MASK ], max_bits );
342 break;
343 }
344 }
345 }
346
347
348
349
350
351
352/****************************************************************/
353/* */
354/* Draw_Strings( state ) */
355/* */
356/* The first status line contains the device name, */
357/* the current write file name (if one is open) */
358/* and the current search string (if one has */
359/* been defined). */
360/* */
361/* Long strings are truncated. */
362/* */
363/****************************************************************/
364
365
366void Draw_Strings( s )
367 de_state *s;
368
369 {
370 int len;
371 int i;
372
373 Goto( STATUS_COLUMN, STATUS_LINE );
374
375 printf( "Device %s= %-14.14s ",
376 s->device_mode == O_RDONLY ? "" : "(w) ", s->device_name );
377
378 switch ( s->magic )
379 {
380 case SUPER_MAGIC : printf( "V1 file system ");
381 break;
382 case SUPER_REV : printf( "V1-bytes-swapped file system (?) ");
383 break;
384 case SUPER_V2 : printf( "V2 file system ");
385 break;
386 case SUPER_V2_REV : printf( "V2-bytes-swapped file system (?) ");
387 break;
388 case SUPER_V3 : printf( "V3 file system ");
389 break;
390 default : printf( "not a Minix file system ");
391 break;
392 }
393
394 len = strlen( s->file_name );
395
396 if ( len == 0 )
397 printf( "%29s", " " );
398 else if ( len <= 20 )
399 printf( "File = %-20s ", s->file_name );
400 else
401 printf( "File = ...%17.17s ", s->file_name + len - 17 );
402
403
404 len = strlen( s->search_string );
405
406 if ( len == 0 )
407 printf( "%20s", " " );
408 else
409 {
410 printf( "Search = " );
411
412 if ( len <= 11 )
413 {
414 for ( i = 0; i < len; ++i )
415 Print_Ascii( s->search_string[ i ] );
416
417 for ( ; i < 11; ++i )
418 putchar( ' ' );
419 }
420 else
421 {
422 for ( i = 0; i < 8; ++i )
423 Print_Ascii( s->search_string[ i ] );
424
425 printf( "..." );
426 }
427 }
428 }
429
430
431
432
433
434
435/****************************************************************/
436/* */
437/* Block_Type( state ) */
438/* */
439/* Display the current block type. */
440/* */
441/****************************************************************/
442
443
444void Block_Type( s )
445 de_state *s;
446
447 {
448 Goto( STATUS_COLUMN, STATUS_LINE + 1 );
449
450 printf( "Block = %5u of %-5u ", s->block, s->zones );
451
452 if ( !s->is_fs )
453 return;
454
455 if ( s->block == BOOT_BLOCK )
456 printf( "Boot block" );
457
458 else if ( s->block == 1 )
459 printf( "Super block" );
460
461 else if ( s->block < 2 + s->inode_maps )
462 printf( "I-node bit map" );
463
464 else if ( s->block < 2 + s->inode_maps + s->zone_maps )
465 printf( "Zone bit map" );
466
467 else if ( s->block < s->first_data )
468 printf( "I-nodes" );
469
470 else
471 printf( "Data block (%sin use)",
472 In_Use( (bit_t) (s->block - (s->first_data - 1)), s->zone_map )
473 ? "" : "not " );
474 }
475
476
477
478
479
480
481/****************************************************************/
482/* */
483/* Draw_Words( state ) */
484/* */
485/* Draw a page in word format. */
486/* */
487/****************************************************************/
488
489
490void Draw_Words( s )
491 de_state *s;
492
493 {
494 int line;
495 int addr = s->offset & ~ PAGE_MASK;
496
497
498 for ( line = 0; line < 16; ++line, addr += 2 )
499 {
500 Goto( BLOCK_COLUMN, BLOCK_LINE + line );
501
502 printf( "%5d ", addr );
503
504 Print_Number( *( (word_t *) &s->buffer[ addr ] ), s->output_base );
505 }
506
507 Goto( BLOCK_COLUMN + 64, BLOCK_LINE );
508 printf( "(base %d)", s->output_base );
509 }
510
511
512
513
514
515
516/****************************************************************/
517/* */
518/* Draw_Info( state ) */
519/* */
520/* Add information to a page drawn in word format. */
521/* The routine recognizes the super block, inodes, */
522/* executables and "ar" archives. If the current */
523/* page is not one of these, then ASCII characters */
524/* are printed from the data words. */
525/* */
526/****************************************************************/
527
528
529char *super_block_info[] = { "number of inodes",
530 "V1 number of zones",
531 "inode bit map blocks",
532 "zone bit map blocks",
533 "first data zone",
534 "blocks per zone shift & flags",
535 "maximum file size",
536 "",
537 "magic number",
538 "fsck magic number",
539 "V2 number of zones" };
540
541
542void Draw_Info( s )
543 de_state *s;
544
545 {
546 int i;
547 int page = s->offset >> PAGE_SHIFT;
548 dev_t dev;
549
550
551 if ( s->is_fs && s->block == 1 && page == 0 )
552 for ( i = 0; i < 11; ++i )
553 {
554 Goto( INFO_COLUMN, INFO_LINE + i );
555 printf( "%s", super_block_info[ i ] );
556 }
557
558 else if ( s->is_fs && s->block >= s->first_data - s->inode_blocks &&
559 s->block < s->first_data )
560 {
561 struct inode core_inode;
562 d1_inode *dip1;
563 d2_inode *dip2;
564 struct inode *inode = &core_inode;
565 int special = 0;
566 int m;
567 struct passwd *user;
568 struct group *grp;
569
570 dip1 = (d1_inode *) &s->buffer[ s->offset & ~ PAGE_MASK ];
571 dip2 = (d2_inode *) &s->buffer[ s->offset & ~ PAGE_MASK
572 & ~ (V2_INODE_SIZE-1) ];
573 conv_inode( inode, dip1, dip2, READING, s->magic );
574
575 user = getpwuid( inode->i_uid );
576 grp = getgrgid( inode->i_gid );
577
578 if ( s->magic != SUPER_MAGIC && page & 1 )
579 {
580 Draw_Zone_Numbers( s, inode, 2, 0 );
581 return;
582 }
583
584 Goto( INFO_COLUMN, INFO_LINE );
585
586 switch( inode->i_mode & S_IFMT )
587 {
588 case S_IFDIR : printf( "directory " );
589 break;
590
591 case S_IFCHR : printf( "character " );
592 special = 1;
593 break;
594
595 case S_IFBLK : printf( "block " );
596 special = 1;
597 break;
598
599 case S_IFREG : printf( "regular " );
600 break;
601#ifdef S_IFIFO
602 case S_IFIFO : printf( "fifo " );
603 break;
604#endif
605#ifdef S_IFLNK
606 case S_IFLNK : printf( "symlink " );
607 break;
608#endif
609#ifdef S_IFSOCK
610 case S_IFSOCK: printf( "socket " );
611 break;
612#endif
613 default : printf( "unknown " );
614 }
615
616 for ( m = 11; m >= 0; --m )
617 putchar( (inode->i_mode & (1<<m)) ? "xwrxwrxwrtgu"[m] : '-' );
618
619 if ( s->magic == SUPER_MAGIC )
620 {
621 /* V1 file system */
622 Goto( INFO_COLUMN, INFO_LINE + 1 );
623 printf( "user %s", user ? user->pw_name : "" );
624
625 Goto( INFO_COLUMN, INFO_LINE + 2 );
626 printf( "file size %lu", inode->i_size );
627
628 Goto( INFO_COLUMN, INFO_LINE + 4 );
629 printf( "m_time %s", ctime( &inode->i_mtime ) );
630
631 Goto( INFO_COLUMN, INFO_LINE + 6 );
632 printf( "links %d, group %s",
633 inode->i_nlinks, grp ? grp->gr_name : "" );
634
635 Draw_Zone_Numbers( s, inode, 0, 7 );
636 }
637 else
638 {
639 /* V2 file system, even page. */
640 Goto( INFO_COLUMN, INFO_LINE + 1 );
641 printf( "links %d ", inode->i_nlinks);
642
643 Goto( INFO_COLUMN, INFO_LINE + 2 );
644 printf( "user %s", user ? user->pw_name : "" );
645
646 Goto( INFO_COLUMN, INFO_LINE + 3 );
647 printf( "group %s", grp ? grp->gr_name : "" );
648
649 Goto( INFO_COLUMN, INFO_LINE + 4 );
650 printf( "file size %lu", inode->i_size );
651
652 Goto( INFO_COLUMN, INFO_LINE + 6 );
653 printf( "a_time %s", ctime( &inode->i_atime ) );
654
655 Goto( INFO_COLUMN, INFO_LINE + 8 );
656 printf( "m_time %s", ctime( &inode->i_mtime ) );
657
658 Goto( INFO_COLUMN, INFO_LINE + 10 );
659 printf( "c_time %s", ctime( &inode->i_ctime ) );
660
661 Draw_Zone_Numbers( s, inode, 0, 12 );
662 }
663
664 if ( special )
665 {
666 Goto( INFO_COLUMN, INFO_LINE + 7 );
667 dev = (dev_t) inode->i_zone[0];
668 printf( "major %d, minor %d", major(dev), minor(dev) );
669 }
670 }
671
672 else /* Print ASCII characters for each byte in page */
673 {
674 char *p = &s->buffer[ s->offset & ~ PAGE_MASK ];
675
676 for ( i = 0; i < 16; ++i )
677 {
678 Goto( INFO_COLUMN, INFO_LINE + i );
679 Print_Ascii( *p++ );
680 Print_Ascii( *p++ );
681 }
682
683 if ( s->block >= s->first_data && page == 0 )
684 {
685 unsigned magic = ((s->buffer[1] & 0xff) << 8) | (s->buffer[0] & 0xff);
686 unsigned second = ((s->buffer[3] & 0xff) << 8) | (s->buffer[2] & 0xff);
687
688 /* Is this block the start of an executable file? */
689
690 if ( magic == (unsigned) A_OUT )
691 {
692 Goto( INFO_COLUMN, INFO_LINE );
693 printf( "executable" );
694
695 Goto( INFO_COLUMN, INFO_LINE + 1 );
696
697 if ( second == (unsigned) SPLIT )
698 printf( "separate I & D" );
699 else
700 printf( "combined I & D" );
701 }
702 }
703 }
704 }
705
706
707
708
709
710
711/****************************************************************/
712/* */
713/* Draw_Block( block ) */
714/* */
715/* Redraw a 1k block in character format. */
716/* */
717/****************************************************************/
718
719
720void Draw_Block( block )
721 char *block;
722
723 {
724 int line;
725 int column;
726 int reverse = 0;
727 int msb_flag = 0;
728
729
730 for ( line = 0; line < 16; ++line )
731 {
732 Goto( BLOCK_COLUMN, BLOCK_LINE + line );
733
734 for ( column = 0; column < 64; ++column )
735 {
736 char c = *block++;
737
738 if ( c & 0x80 )
739 {
740 msb_flag = 1;
741 c &= 0x7f;
742 }
743
744 if ( c >= ' ' && c < DEL )
745 {
746 if ( reverse )
747 { fputs( Tnormal, stdout ); reverse = 0; }
748
749 putchar( c );
750 }
751 else
752 {
753 if ( ! reverse )
754 { fputs( Treverse, stdout ); reverse = 1; }
755
756 putchar( c == DEL ? '?' : '@' + c );
757 }
758 } /* end for ( column ) */
759 } /* end for ( line ) */
760
761 if ( reverse )
762 { fputs( Tnormal, stdout ); reverse = 0; }
763
764 if ( msb_flag )
765 {
766 Goto( BLOCK_COLUMN + 68, BLOCK_LINE + 6 );
767 fputs( "(MSB)", stdout );
768 }
769 }
770
771
772
773
774
775
776/****************************************************************/
777/* */
778/* Draw_Map( block, max_bits ) */
779/* */
780/* Redraw a block in a bit map format. */
781/* Display min( max_bits, 2048 ) bits. */
782/* */
783/* The 256 bytes in "block" are displayed from */
784/* top to bottom and left to right. Bit 0 of */
785/* a byte is towards the top of the screen. */
786/* */
787/* Special graphic codes are used to generate */
788/* two "bits" per character position. So a 16 */
789/* line by 64 column display is 32 "bits" by */
790/* 64 "bits". Or 4 bytes by 64 bytes. */
791/* */
792/****************************************************************/
793
794
795void Draw_Map( block, max_bits )
796 char *block;
797 int max_bits;
798
799 {
800 int line;
801 int column;
802 int bit_count = 0;
803
804 for ( line = 0; line < 16; ++line )
805 {
806 char *p = &block[ (line & 0xC) >> 2 ];
807 int shift = (line & 0x3) << 1;
808
809 Goto( BLOCK_COLUMN, BLOCK_LINE + line );
810
811 for ( column = 0; column < 64; ++column, p += 4 )
812 {
813 char c = (*p >> shift) & 0x3;
814 int current_bit = ((p - block) << 3) + shift;
815
816 /* Don't display bits past "max_bits" */
817
818 if ( current_bit >= max_bits )
819 break;
820
821 /* If "max_bits" occurs in between the two bits */
822 /* I am trying to display as one character, then */
823 /* zero off the high-order bit. */
824
825 if ( current_bit + 1 == max_bits )
826 c &= 1;
827
828 switch ( c )
829 {
830 case 0 : putchar( BOX_CLR );
831 break;
832
833 case 1 : putchar( BOX_TOP );
834 ++bit_count;
835 break;
836
837 case 2 : putchar( BOX_BOT );
838 ++bit_count;
839 break;
840
841 case 3 : putchar( BOX_ALL );
842 bit_count += 2;
843 break;
844 }
845 } /* end for ( column ) */
846 } /* end for ( line ) */
847
848
849 Goto( BLOCK_COLUMN + 68, BLOCK_LINE + 6 );
850 printf( "(%d)", bit_count );
851 }
852
853
854
855
856
857
858/****************************************************************/
859/* */
860/* Draw_Pointers( state ) */
861/* */
862/* Redraw the pointers and the offset field. */
863/* The rest of the screen stays intact. */
864/* */
865/****************************************************************/
866
867
868void Draw_Pointers( s )
869 de_state *s;
870
871 {
872 Draw_Offset( s );
873
874 switch ( s->mode )
875 {
876 case WORD : Word_Pointers( s->last_addr, s->address );
877 break;
878
879 case BLOCK : Block_Pointers( s->last_addr, s->address );
880 break;
881
882 case MAP : Map_Pointers( s->last_addr, s->address );
883 break;
884 }
885
886 Goto( PROMPT_COLUMN, PROMPT_LINE );
887 }
888
889
890
891
892
893
894/****************************************************************/
895/* */
896/* Draw_Offset( state ) */
897/* */
898/* Display the offset in the current buffer */
899/* and the relative position if within a map */
900/* or i-node block. */
901/* */
902/****************************************************************/
903
904
905void Draw_Offset( s )
906 de_state *s;
907
908 {
909 Goto( STATUS_COLUMN, STATUS_LINE + 2 );
910
911 printf( "Offset = %5d ", s->offset );
912
913
914 if ( s->block < 2 )
915 return;
916
917 if ( s->block < 2 + s->inode_maps )
918 {
919 long bit = (s->address - 2 * K) * 8;
920
921 if ( bit < s->inodes_in_map )
922 printf( "I-node %ld of %d ", bit, s->inodes );
923 else
924 printf( "(padding) " );
925 }
926
927 else if ( s->block < 2 + s->inode_maps + s->zone_maps )
928 {
929 long bit = (s->address - (2 + s->inode_maps) * K) * 8;
930
931 if ( bit < s->zones_in_map )
932 printf( "Block %ld of %u ", bit + s->first_data - 1, s->zones );
933 else
934 printf( "(padding) " );
935 }
936
937 else if ( s->block < s->first_data )
938 {
939 bit_t node = (s->address - (2 + s->inode_maps + s->zone_maps) * K) /
940 s->inode_size + 1;
941
942 if ( node <= s->inodes )
943 printf( "I-node %lu of %lu (%sin use) ",
944 (unsigned long) node, (unsigned long) s->inodes,
945 In_Use( node, s->inode_map ) ? "" : "not " );
946 else
947 printf( "(padding) " );
948 }
949 }
950
951
952
953
954
955
956/****************************************************************/
957/* */
958/* Word_Pointers( old_addr, new_addr ) */
959/* */
960/* Block_Pointers( old_addr, new_addr ) */
961/* */
962/* Map_Pointers( old_addr, new_addr ) */
963/* */
964/* Redraw the index pointers for a each type */
965/* of display. The pointer at "old_addr" is */
966/* erased and a new pointer is positioned */
967/* for "new_addr". This makes the screen */
968/* update faster and more pleasant for the user. */
969/* */
970/****************************************************************/
971
972
973void Word_Pointers( old_addr, new_addr )
974 off_t old_addr;
975 off_t new_addr;
976
977 {
978 int from = ( (int) old_addr & PAGE_MASK ) >> 1;
979 int to = ( (int) new_addr & PAGE_MASK ) >> 1;
980
981 Goto( BLOCK_COLUMN - 2, BLOCK_LINE + from );
982 putchar( ' ' );
983
984 Goto( BLOCK_COLUMN - 2, BLOCK_LINE + to );
985 putchar( '>' );
986 }
987
988
989
990
991void Block_Pointers( old_addr, new_addr )
992 off_t old_addr;
993 off_t new_addr;
994
995 {
996 int from = (int) old_addr & ~K_MASK;
997 int to = (int) new_addr & ~K_MASK;
998
999 Goto( BLOCK_COLUMN - 2, BLOCK_LINE + from / 64 );
1000 putchar( ' ' );
1001
1002 Goto( BLOCK_COLUMN - 2, BLOCK_LINE + to / 64 );
1003 putchar( '>' );
1004
1005 Goto( BLOCK_COLUMN + from % 64, BLOCK_LINE + 17 );
1006 putchar( ' ' );
1007
1008 Goto( BLOCK_COLUMN + to % 64, BLOCK_LINE + 17 );
1009 putchar( '^' );
1010 }
1011
1012
1013
1014
1015void Map_Pointers( old_addr, new_addr )
1016 off_t old_addr;
1017 off_t new_addr;
1018
1019 {
1020 int from = ( (int) old_addr & MAP_MASK ) >> 2;
1021 int to = ( (int) new_addr & MAP_MASK ) >> 2;
1022
1023 Goto( BLOCK_COLUMN + from, BLOCK_LINE + 17 );
1024 putchar( ' ' );
1025
1026 Goto( BLOCK_COLUMN + to, BLOCK_LINE + 17 );
1027 putchar( '^' );
1028 }
1029
1030
1031
1032
1033
1034
1035/****************************************************************/
1036/* */
1037/* Print_Number( number, output_base ) */
1038/* */
1039/* Output "number" in the output base. */
1040/* */
1041/****************************************************************/
1042
1043
1044void Print_Number( number, output_base )
1045 word_t number;
1046 int output_base;
1047
1048 {
1049 switch ( output_base )
1050 {
1051 case 16 : printf( "%5x", number );
1052 break;
1053
1054 case 10 : printf( "%7u", number );
1055 break;
1056
1057 case 8 : printf( "%7o", number );
1058 break;
1059
1060 case 2 : {
1061 unsigned int mask;
1062 char pad = ' ';
1063
1064 for ( mask = 0x8000; mask > 1; mask >>= 1 )
1065 putchar( (mask & number) ? (pad = '0', '1') : pad );
1066
1067 putchar( (0x01 & number) ? '1' : '0' );
1068
1069 break;
1070 }
1071
1072 default : Error( "Internal fault (output_base)" );
1073 }
1074 }
1075
1076
1077
1078
1079
1080
1081/****************************************************************/
1082/* */
1083/* Print_Ascii( char ) */
1084/* */
1085/* Display a character in reverse mode if it */
1086/* is not a normal printable ASCII character. */
1087/* */
1088/****************************************************************/
1089
1090
1091void Print_Ascii( c )
1092 char c;
1093
1094 {
1095 c &= 0x7f;
1096
1097 if ( c < ' ' )
1098 printf( "%s%c%s", Treverse, '@' + c, Tnormal );
1099 else if ( c == DEL )
1100 printf( "%s?%s", Treverse, Tnormal );
1101 else
1102 putchar( c );
1103 }
1104
1105
1106
1107
1108
1109
1110/****************************************************************/
1111/* */
1112/* Warning( text, arg1, arg2 ) */
1113/* */
1114/* Display a message for 2 seconds. */
1115/* */
1116/****************************************************************/
1117
1118
1119#if __STDC__
1120void Warning( const char *text, ... )
1121#else
1122void Warning( text )
1123 char *text;
1124#endif
1125
1126 {
1127 va_list argp;
1128
1129 printf( "%c%s", BELL, Tclr_all );
1130
1131 Goto( WARNING_COLUMN, WARNING_LINE );
1132
1133 printf( "%s Warning: ", Treverse );
1134 va_start( argp, text );
1135 vprintf( text, argp );
1136 va_end( argp );
1137 printf( " %s", Tnormal );
1138
1139 fflush(stdout); /* why does everyone forget this? */
1140
1141 sleep( 2 );
1142 }
1143
1144
1145void Draw_Zone_Numbers( s, inode, zindex, zrow )
1146 de_state *s;
1147 struct inode *inode;
1148 int zindex;
1149 int zrow;
1150
1151 {
1152 static char *plurals[] = { "", "double ", "triple " };
1153 zone_t zone;
1154
1155 for ( ; zrow < 16;
1156 ++zindex, zrow += s->zone_num_size / sizeof (word_t) )
1157 {
1158 Goto( INFO_COLUMN, INFO_LINE + zrow );
1159 if ( zindex < s->ndzones )
1160 printf( "zone %d", zindex );
1161 else
1162 printf( "%sindirect", plurals[ zindex - s->ndzones ] );
1163 if ( s->magic != SUPER_MAGIC )
1164 {
1165 zone = inode->i_zone[ zindex ];
1166 if ( zone != (word_t) zone )
1167 {
1168 Goto( INFO_COLUMN + 16, INFO_LINE + zrow );
1169 printf("%ld", (long) zone );
1170 }
1171 }
1172 }
1173 }
Note: See TracBrowser for help on using the repository browser.