1 /******************************************************************************\
2  *  Copyright (C) 2001 writen by Jewfish and Armoth                           *
3  *									      *
4  *  Description: this codes allows a user to view and edit the hexadecimal and*
5  *		 and ascii values of a file.  The curses library is used to   *
6  *		 display and manipulate the output.  See the README file      *
7  *		 included for more information.				      *
8  *									      *
9  *  This program is free software; you can redistribute it and/or modify      *
10  *  it under the terms of the GNU General Public License as published by      *
11  *  the Free Software Foundation; either version 2 of the License, or	      *
12  *  (at your option) any later version.					      *
13  *									      *
14  *  This program is distributed in the hope that it will be useful,	      *
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of	      *
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the	      *
17  *  GNU General Public License for more details.			      *
18  *									      *
19  *  You should have received a copy of the GNU General Public License	      *
20  *  along with this program; if not, write to the Free Software		      *
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *
22  *									      *
23 \******************************************************************************/
24 
25 #include "hex.h"					/* custom header      */
26 
27 /*#define DEBUG_LLIST*/
28 /*#define DEBUG_GOTO*/
29 
30 int     BASE, MAXY, resize = 0;
31 int     MIN_ADDR_LENGTH;
32 hexList *head;						/* linked list struct */
33 WINS    *windows;					/* window structure   */
34 char    EBCDIC[256],
35 	*fpINfilename = NULL,
36         *fpOUTfilename = NULL;
37 bool 	printHex;					/* address format     */
38 bool    USE_EBCDIC;
39 bool    IN_HELP;					/* if help displayed  */
40 int     hex_win_width,
41         ascii_win_width,
42         hex_outline_width,
43         ascii_outline_width;
44 
45 
46     /* partial EBCDIC table contributed by Ted (ted@php.net) */
47     char EBCDIC[] = {
48     /* 0   1   2   3   4   5   6   7   8   9   A   B   C   D    E   F */
49       '.','.','.','.','.','.','.','.','.','.','.','.','.','.' ,'.','.', /* 0 */
50       '.','.','.','.','.','.','.','.','.','.','.','.','.','.' ,'.','.', /* 1 */
51       '.','.','.','.','.','.','.','.','.','.','.','.','.','.' ,'.','.', /* 2 */
52       '.','.','.','.','.','.','.','.','.','.','.','.','.','.' ,'.','.', /* 3 */
53       ' ','.','.','.','.','.','.','.','.','.','.','.','<','(' ,'+','|', /* 4 */
54       '&','.','.','.','.','.','.','.','.','.','!','$','*',')' ,';','.', /* 5 */
55       '-','/','.','.','.','.','.','.','.','.','.',',','%','_' ,'>','?', /* 6 */
56       '.','.','.','.','.','.','.','.','.','.',':','#','@','\'','=','"', /* 7 */
57       '.','a','b','c','d','e','f','g','h','i','.','.','.','.' ,'.','.', /* 8 */
58       '.','.','j','k','l','m','n','o','p','q','.','.','.','.' ,'.','.', /* 9 */
59       '.','r','s','t','u','v','w','x','y','z','.','.','.','.' ,'.','.', /* A */
60       '.','.','.','.','.','.','.','.','.','`','.','.','.','.' ,'.','.', /* B */
61       '.','A','B','C','D','E','F','G','H','I','.','.','.','.' ,'.','.', /* C */
62       '.','.','J','K','L','M','N','O','P','Q','.','.','.','.' ,'.','.', /* D */
63       '.','R','S','T','U','V','W','X','Y','Z','.','.','.','.' ,'.','.', /* E */
64       '0','1','2','3','4','5','6','7','8','9','.','.','.','.' ,'.','.'};/* F */
65 
main(int argc,char * argv[])66 int main(int argc, char *argv[])			/* main program       */
67 {
68 
69     int   x, retval = 1;			/* counters, etc.     */
70     off_t val, len;					/* len need to be off_t*/
71 
72     windows = (WINS *) calloc(1, sizeof(WINS));	/* malloc windows     */
73     head = llalloc();							/* malloc list space  */
74     fpINfilename = NULL;			/* allocate in and    */
75     fpOUTfilename = NULL;			/* out file name ptrs */
76     printHex = TRUE;							/* address format     */
77     USE_EBCDIC = FALSE;							/*use ascii by default*/
78 
79 							/* get cmd line args  */
80     len = parseArgs(argc, argv);
81     MIN_ADDR_LENGTH = getMinimumAddressLength(len);
82 
83     use_env(TRUE);					/* use env values     */
84     slk_init(0);					/* init menu bar      */
85     init_screen();					/* init visuals       */
86     init_colors();
87 
88     if ((COLS < MIN_COLS) || (LINES < MIN_LINES))	/* screen's too small */
89     {
90 	endwin();
91 	fprintf(stderr,"\n\nThe screen size too small.\nThe minimum allowable");
92 	fprintf(stderr," screen size is %dx%d\n\n", MIN_COLS, MIN_LINES + 1);
93 	exit(-1);
94     }
95 
96     slk_set(6, (printHex) ? "Hex Addr":"Dec Addr", 1);
97     init_fkeys();					/* define menu bar    */
98 
99 
100     while (retval)
101     {
102 	free_windows(windows);
103 
104 	/* calculate screen   */
105 	BASE                = (resize > 0 && resize < COLS) ? resize:((COLS-6-MIN_ADDR_LENGTH)/4);
106 	MAXY                = (LINES) - 3;
107 	hex_win_width       = BASE * 3;
108 	ascii_win_width     = BASE;
109 	hex_outline_width   = (BASE * 3) + 3 + MIN_ADDR_LENGTH;
110 	ascii_outline_width = BASE + 2;
111 
112 	init_menu(windows);				/* init windows       */
113 	head = freeList(head);				/* free & init head   */
114 							/* print origin loc   */
115 	mvwprintw(windows->hex_outline, 0, 1, "%0*d", MIN_ADDR_LENGTH, 0);
116 
117 	if (fpIN != NULL)				/* if no infile...    */
118 	{
119             len = maxLoc(fpIN);				/* get last file loc  */
120 	    val = maxLines(len); 			/* max file lines     */
121             for (x = 0; x <= MAXY && x<=val; x++)       /* output lines       */
122 		outline(fpIN, x);
123 	}
124 
125 	wmove(windows->hex, 0, 0);			/* cursor to origin   */
126 
127 	refreshall(windows);				/* refresh all wins   */
128 	doupdate();					/* update screen      */
129 
130 	mvwaddch(windows->scrollbar, 1, 0, ACS_CKBOARD);/* clear scroller     */
131 							/* get user input     */
132 	retval = wacceptch(windows, len);
133     }
134 
135     free(fpINfilename);
136     free(fpOUTfilename);
137     freeList(head);
138 
139     screen_exit(0);					/* end visualizations */
140     return retval;					/* return             */
141 }
142 
143 /********************************************************\
144  * Description: prints out debug info to a file         *
145  * Returns:     nothing                                 *
146 \********************************************************/
147 /*
148 void printDebug(hexList *head, long int loc)
149 {
150     FILE *tmpofp;
151     hexList *tmpHead = head;
152 
153     tmpofp = fopen("debug_llist", "a+");
154     tmpHead = head;
155 
156     fprintf(tmpofp, "location undone: %08X\n", loc);
157     while (tmpHead != NULL)
158     {
159 	fprintf(tmpofp, "head->loc: %08X   head->val: %02X (%c)\n", tmpHead->loc, tmpHead->val, tmpHead->val);
160 
161 	tmpHead = tmpHead->next;
162     }
163     fprintf(tmpofp, "\n");
164 
165     fclose(tmpofp);
166 }
167 */
168 
169 /********************************************************\
170  * Description: parses command line arguments and 	*
171  *		processes them.				*
172  * Returns:	length of file				*
173 \********************************************************/
parseArgs(int argc,char * argv[])174 off_t parseArgs(int argc, char *argv[])
175 {
176     extern char *optarg;				/* extern vars for    */
177     extern int optind, /*opterr,*/ optopt;		/* getopt()	      */
178 
179     int val;						/* counters, etc.     */
180 
181 							/* get args           */
182     while ((val = hgetopt(argc, argv, "a:i:o:r:e")) != -1)
183     {
184 	switch (val)					/* test args          */
185         {
186             case 'a':	printHex = FALSE;		/* decimal addresses  */
187                         break;
188 							/* infile             */
189 	    case 'i':	free(fpINfilename);
190 			fpINfilename = strdup(optarg);
191 			break;
192 							/* outfile            */
193 	    case 'o':   free(fpOUTfilename);
194 			fpOUTfilename = strdup(optarg);
195 			break;
196 
197             case 'r':   resize = atoi(optarg);		/* don't resize screen*/
198                         break;
199 
200             case 'e':   USE_EBCDIC=TRUE;		/*use instead of ascii*/
201                         break;
202 							/* help/invalid args  */
203 							/* help/invalid args  */
204 	    case '?':	print_usage();			/* output help        */
205                         if ((optopt == 'h') || (optopt == '?'))
206 			    exit(0);			/* exit               */
207 			else				/* illegal option     */
208 			    exit(-1);
209         }
210     }
211     argc -= optind;
212     argv += optind;
213 
214     if (argv[0])
215     {
216 	free(fpINfilename);
217         fpINfilename = strdup(argv[0]);
218     }
219 
220     if (fpINfilename && strcmp(fpINfilename, ""))
221         if ((fpIN = fopen(fpINfilename, "r")) == NULL)
222             exit_err("Could not open file");
223 
224     return ((fpIN != NULL) ? maxLoc(fpIN):0);		/* return file length */
225 }
226 
227 /********************************************************\
228  * Description: Get the minimum address length for the  *
229  *              address column                          *
230  * Returns:	minimum length for addresses		*
231 \********************************************************/
getMinimumAddressLength(off_t len)232 int getMinimumAddressLength(off_t len)
233 {
234         char buffer[1];
235         int min_address_length;
236 
237         min_address_length = snprintf(buffer, 1, "%jd", (intmax_t)len);
238 
239         /* At least 8 characters wide */
240         return min_address_length > 8 ? min_address_length : 8;
241 }
242 
243 /********************************************************\
244  * Description: in the event of a segmentation fault    *
245  * 		this catches the signal and prints out  *
246  *		instructions on where to send a bug     *
247  * 		report.					*
248  * Returns:	length of file				*
249 \********************************************************/
catchSegfault(int sig)250 RETSIGTYPE catchSegfault(int sig)
251 {
252     /* Avoid unused variable warning */
253     UNUSED(sig);
254 
255     endwin();
256     printf("\n\nHexcurse has encountered a segmentation fault!\n");
257     printf("\tPlease submit a full bug report to devel@jewfish.net.\n");
258     printf("\tInclude what you did to cause the segfault, and if possible\n");
259     printf("\tinclude the core dump.  And for your troubles, we'll add you \n");
260     printf("\tto the Changelog. Then you can brag to your friends about it!\n");
261 
262     exit(-1);
263 }
264