xref: /aosp_15_r20/external/e2fsprogs/ext2ed/main.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker 
3*6a54128fSAndroid Build Coastguard Worker /usr/src/ext2ed/main.c
4*6a54128fSAndroid Build Coastguard Worker 
5*6a54128fSAndroid Build Coastguard Worker A part of the extended file system 2 disk editor.
6*6a54128fSAndroid Build Coastguard Worker 
7*6a54128fSAndroid Build Coastguard Worker ------------
8*6a54128fSAndroid Build Coastguard Worker Main program
9*6a54128fSAndroid Build Coastguard Worker ------------
10*6a54128fSAndroid Build Coastguard Worker 
11*6a54128fSAndroid Build Coastguard Worker This file mostly contains:
12*6a54128fSAndroid Build Coastguard Worker 
13*6a54128fSAndroid Build Coastguard Worker 1.	A list of global variables used through the entire program.
14*6a54128fSAndroid Build Coastguard Worker 2.	The parser, which asks the command line from the user.
15*6a54128fSAndroid Build Coastguard Worker 3.	The dispatcher, which analyzes the command line and calls the appropriate handler function.
16*6a54128fSAndroid Build Coastguard Worker 4.	A command pattern matcher which is used along with the readline completion feature.
17*6a54128fSAndroid Build Coastguard Worker 5.	A function which tells the user that an internal error has occurred.
18*6a54128fSAndroid Build Coastguard Worker 
19*6a54128fSAndroid Build Coastguard Worker First written on: March 30 1995
20*6a54128fSAndroid Build Coastguard Worker 
21*6a54128fSAndroid Build Coastguard Worker Copyright (C) 1995 Gadi Oxman
22*6a54128fSAndroid Build Coastguard Worker 
23*6a54128fSAndroid Build Coastguard Worker */
24*6a54128fSAndroid Build Coastguard Worker 
25*6a54128fSAndroid Build Coastguard Worker #include "config.h"
26*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
27*6a54128fSAndroid Build Coastguard Worker #include <stdlib.h>
28*6a54128fSAndroid Build Coastguard Worker #include <string.h>
29*6a54128fSAndroid Build Coastguard Worker #include <signal.h>
30*6a54128fSAndroid Build Coastguard Worker 
31*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_READLINE
32*6a54128fSAndroid Build Coastguard Worker #include <readline.h>
33*6a54128fSAndroid Build Coastguard Worker #include <history.h>
34*6a54128fSAndroid Build Coastguard Worker #endif
35*6a54128fSAndroid Build Coastguard Worker 
36*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETOPT_H
37*6a54128fSAndroid Build Coastguard Worker #include <getopt.h>
38*6a54128fSAndroid Build Coastguard Worker #else
39*6a54128fSAndroid Build Coastguard Worker extern int optind;
40*6a54128fSAndroid Build Coastguard Worker extern char *optarg;
41*6a54128fSAndroid Build Coastguard Worker #endif
42*6a54128fSAndroid Build Coastguard Worker 
43*6a54128fSAndroid Build Coastguard Worker #include "ext2ed.h"
44*6a54128fSAndroid Build Coastguard Worker 
45*6a54128fSAndroid Build Coastguard Worker /* Global variables */
46*6a54128fSAndroid Build Coastguard Worker 
47*6a54128fSAndroid Build Coastguard Worker /*
48*6a54128fSAndroid Build Coastguard Worker 
49*6a54128fSAndroid Build Coastguard Worker Configuration file options
50*6a54128fSAndroid Build Coastguard Worker 
51*6a54128fSAndroid Build Coastguard Worker The following variables will be set by init.c to the values selected in the user configuration file.
52*6a54128fSAndroid Build Coastguard Worker They are initialized below to some logical defaults.
53*6a54128fSAndroid Build Coastguard Worker 
54*6a54128fSAndroid Build Coastguard Worker */
55*6a54128fSAndroid Build Coastguard Worker 
56*6a54128fSAndroid Build Coastguard Worker 
57*6a54128fSAndroid Build Coastguard Worker char Ext2Descriptors [200]="ext2.descriptors";	/* The location of the ext2 filesystem object definition */
58*6a54128fSAndroid Build Coastguard Worker char AlternateDescriptors [200]="";		/* We allow the user to define additional structures */
59*6a54128fSAndroid Build Coastguard Worker char LogFile [200]="ext2ed.log";		/* The location of the log file - Each write will be logged there */
60*6a54128fSAndroid Build Coastguard Worker int LogChanges=1;				/* 1 enables logging, 0 disables logging */
61*6a54128fSAndroid Build Coastguard Worker int AllowChanges=0;				/* When set, the enablewrite command will fail */
62*6a54128fSAndroid Build Coastguard Worker int AllowMountedRead=0;				/* Behavior when trying to open a mounted filesystem read-only */
63*6a54128fSAndroid Build Coastguard Worker int ForceExt2=0;				/* When set, ext2 autodetection is overridden */
64*6a54128fSAndroid Build Coastguard Worker int DefaultBlockSize=1024;
65*6a54128fSAndroid Build Coastguard Worker unsigned long DefaultTotalBlocks=2097151;
66*6a54128fSAndroid Build Coastguard Worker unsigned long DefaultBlocksInGroup=8192;	/* The default values are used when an ext2 filesystem is not */
67*6a54128fSAndroid Build Coastguard Worker int ForceDefault=0;				/* detected, or ForceDefault is set */
68*6a54128fSAndroid Build Coastguard Worker 
69*6a54128fSAndroid Build Coastguard Worker char last_command_line [80];			/* A simple one command cache, in addition to the readline history */
70*6a54128fSAndroid Build Coastguard Worker 
71*6a54128fSAndroid Build Coastguard Worker char device_name [80];				/* The location of the filesystem */
72*6a54128fSAndroid Build Coastguard Worker FILE *device_handle=NULL;			/* This is passed to the fopen / fread ... commands */
73*6a54128fSAndroid Build Coastguard Worker long device_offset;				/* The current position in the filesystem */
74*6a54128fSAndroid Build Coastguard Worker 						/* Note that we have a 2 GB limitation */
75*6a54128fSAndroid Build Coastguard Worker 
76*6a54128fSAndroid Build Coastguard Worker int mounted=0;					/* This is set when we find that the filesystem is mounted */
77*6a54128fSAndroid Build Coastguard Worker 
78*6a54128fSAndroid Build Coastguard Worker struct struct_commands general_commands,ext2_commands;		/* Used to define the general and ext2 commands */
79*6a54128fSAndroid Build Coastguard Worker struct struct_descriptor *first_type,*last_type,*current_type;	/* Used to access the double linked list */
80*6a54128fSAndroid Build Coastguard Worker struct struct_type_data type_data;				/* The current data is sometimes stored here */
81*6a54128fSAndroid Build Coastguard Worker struct struct_file_system_info file_system_info;		/* Essential information on the filesystem */
82*6a54128fSAndroid Build Coastguard Worker struct struct_file_info file_info,first_file_info;		/* Used by file_com.c to access files */
83*6a54128fSAndroid Build Coastguard Worker struct struct_group_info group_info;				/* Used by group_com.c */
84*6a54128fSAndroid Build Coastguard Worker struct struct_super_info super_info;				/* Used by super_com.c */
85*6a54128fSAndroid Build Coastguard Worker struct struct_remember_lifo remember_lifo;			/* A circular memory of objects */
86*6a54128fSAndroid Build Coastguard Worker struct struct_block_bitmap_info block_bitmap_info;		/* Used by blockbitmap_com.c */
87*6a54128fSAndroid Build Coastguard Worker struct struct_inode_bitmap_info inode_bitmap_info;		/* Used by inodebitmap_com.c */
88*6a54128fSAndroid Build Coastguard Worker 
89*6a54128fSAndroid Build Coastguard Worker int redraw_request=0;						/* Is set by a signal handler to handle terminal */
90*6a54128fSAndroid Build Coastguard Worker 								/* screen size change. */
91*6a54128fSAndroid Build Coastguard Worker 
92*6a54128fSAndroid Build Coastguard Worker 
93*6a54128fSAndroid Build Coastguard Worker /*
94*6a54128fSAndroid Build Coastguard Worker  * We just call the parser to get commands from the user. We quit when
95*6a54128fSAndroid Build Coastguard Worker  * parser returns.
96*6a54128fSAndroid Build Coastguard Worker  */
main(int argc,char ** argv)97*6a54128fSAndroid Build Coastguard Worker int main (int argc, char **argv)
98*6a54128fSAndroid Build Coastguard Worker {
99*6a54128fSAndroid Build Coastguard Worker 	int	write_priv = 0;
100*6a54128fSAndroid Build Coastguard Worker 	int	c;
101*6a54128fSAndroid Build Coastguard Worker 	char	*buf;
102*6a54128fSAndroid Build Coastguard Worker 
103*6a54128fSAndroid Build Coastguard Worker 	if (!init ())
104*6a54128fSAndroid Build Coastguard Worker 		return (1);
105*6a54128fSAndroid Build Coastguard Worker 	while ((c = getopt (argc, argv, "w")) != EOF) {
106*6a54128fSAndroid Build Coastguard Worker 		switch (c) {
107*6a54128fSAndroid Build Coastguard Worker 		case 'w':
108*6a54128fSAndroid Build Coastguard Worker 			write_priv++;
109*6a54128fSAndroid Build Coastguard Worker 			break;
110*6a54128fSAndroid Build Coastguard Worker 		}
111*6a54128fSAndroid Build Coastguard Worker 	}
112*6a54128fSAndroid Build Coastguard Worker 	if (optind < argc) {
113*6a54128fSAndroid Build Coastguard Worker 		buf = malloc(strlen(argv[optind]) + 32);
114*6a54128fSAndroid Build Coastguard Worker 		if (!buf) {
115*6a54128fSAndroid Build Coastguard Worker 			fprintf(stderr, "Couldn't allocate filename buffer\n");
116*6a54128fSAndroid Build Coastguard Worker 			exit(1);
117*6a54128fSAndroid Build Coastguard Worker 		}
118*6a54128fSAndroid Build Coastguard Worker 		strcpy(buf, "set_device ");
119*6a54128fSAndroid Build Coastguard Worker 		strcat(buf, argv[optind]);
120*6a54128fSAndroid Build Coastguard Worker 		set_device(buf);
121*6a54128fSAndroid Build Coastguard Worker 		free(buf);
122*6a54128fSAndroid Build Coastguard Worker 		if (write_priv) {
123*6a54128fSAndroid Build Coastguard Worker 			wprintw (command_win,"\n");
124*6a54128fSAndroid Build Coastguard Worker 			enable_write("enable_write");
125*6a54128fSAndroid Build Coastguard Worker 		}
126*6a54128fSAndroid Build Coastguard Worker 	}
127*6a54128fSAndroid Build Coastguard Worker 	parser ();			/* Get and parse user commands */
128*6a54128fSAndroid Build Coastguard Worker 	prepare_to_close();		/* Do some cleanup */
129*6a54128fSAndroid Build Coastguard Worker 	printf("Quitting ...\n");
130*6a54128fSAndroid Build Coastguard Worker 	return(0);
131*6a54128fSAndroid Build Coastguard Worker }
132*6a54128fSAndroid Build Coastguard Worker 
133*6a54128fSAndroid Build Coastguard Worker 
134*6a54128fSAndroid Build Coastguard Worker /*
135*6a54128fSAndroid Build Coastguard Worker  * Read a character from the command window
136*6a54128fSAndroid Build Coastguard Worker  */
command_read_key()137*6a54128fSAndroid Build Coastguard Worker int command_read_key()
138*6a54128fSAndroid Build Coastguard Worker {
139*6a54128fSAndroid Build Coastguard Worker 	int	key = 0;
140*6a54128fSAndroid Build Coastguard Worker 
141*6a54128fSAndroid Build Coastguard Worker 	while (!key) {
142*6a54128fSAndroid Build Coastguard Worker 		if (redraw_request) {
143*6a54128fSAndroid Build Coastguard Worker 			redraw_all();
144*6a54128fSAndroid Build Coastguard Worker 			redraw_request=0;
145*6a54128fSAndroid Build Coastguard Worker 		}
146*6a54128fSAndroid Build Coastguard Worker 		key = wgetch(command_win);
147*6a54128fSAndroid Build Coastguard Worker 		switch (key) {
148*6a54128fSAndroid Build Coastguard Worker 		case 0x1A:
149*6a54128fSAndroid Build Coastguard Worker 			key = 0;
150*6a54128fSAndroid Build Coastguard Worker 			kill(getpid(), SIGTSTP);
151*6a54128fSAndroid Build Coastguard Worker 			break;
152*6a54128fSAndroid Build Coastguard Worker 
153*6a54128fSAndroid Build Coastguard Worker 		case KEY_NPAGE:
154*6a54128fSAndroid Build Coastguard Worker 			pgdn("");
155*6a54128fSAndroid Build Coastguard Worker 			refresh_command_win ();
156*6a54128fSAndroid Build Coastguard Worker 			break;
157*6a54128fSAndroid Build Coastguard Worker 
158*6a54128fSAndroid Build Coastguard Worker 		case KEY_PPAGE:
159*6a54128fSAndroid Build Coastguard Worker 			pgup("");
160*6a54128fSAndroid Build Coastguard Worker 			refresh_command_win ();
161*6a54128fSAndroid Build Coastguard Worker 			break;
162*6a54128fSAndroid Build Coastguard Worker 		case ERR:
163*6a54128fSAndroid Build Coastguard Worker 			key = 0;
164*6a54128fSAndroid Build Coastguard Worker 			break;
165*6a54128fSAndroid Build Coastguard Worker 
166*6a54128fSAndroid Build Coastguard Worker 		case KEY_BACKSPACE:
167*6a54128fSAndroid Build Coastguard Worker 			key = '\b';
168*6a54128fSAndroid Build Coastguard Worker 		}
169*6a54128fSAndroid Build Coastguard Worker 		if ((key < 32 && key != '\b' && key != '\n') ||
170*6a54128fSAndroid Build Coastguard Worker 		    (key > 127))
171*6a54128fSAndroid Build Coastguard Worker 			key = 0;
172*6a54128fSAndroid Build Coastguard Worker 	}
173*6a54128fSAndroid Build Coastguard Worker 	return key;
174*6a54128fSAndroid Build Coastguard Worker }
175*6a54128fSAndroid Build Coastguard Worker 
176*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_READLINE
rl_getc_replacement(FILE * f)177*6a54128fSAndroid Build Coastguard Worker int rl_getc_replacement(FILE *f)
178*6a54128fSAndroid Build Coastguard Worker {
179*6a54128fSAndroid Build Coastguard Worker 	int	key = command_read_key();
180*6a54128fSAndroid Build Coastguard Worker 
181*6a54128fSAndroid Build Coastguard Worker 	if (key == '\b') {
182*6a54128fSAndroid Build Coastguard Worker 		if (rl_point > 0)
183*6a54128fSAndroid Build Coastguard Worker 			wprintw(command_win, "\b \b");
184*6a54128fSAndroid Build Coastguard Worker 	} else
185*6a54128fSAndroid Build Coastguard Worker 		wprintw(command_win, "%c", key);
186*6a54128fSAndroid Build Coastguard Worker 	return key;
187*6a54128fSAndroid Build Coastguard Worker }
188*6a54128fSAndroid Build Coastguard Worker 
189*6a54128fSAndroid Build Coastguard Worker /*
190*6a54128fSAndroid Build Coastguard Worker  * This function asks the user for a command and calls the dispatcher
191*6a54128fSAndroid Build Coastguard Worker  * function, dispatch, to analyze it.  We use the readline library
192*6a54128fSAndroid Build Coastguard Worker  * function readline to read the command, hence all the usual readline
193*6a54128fSAndroid Build Coastguard Worker  * keys are available.  The new command is saved both in the
194*6a54128fSAndroid Build Coastguard Worker  * readline's history and in our tiny one-command cache, so that only
195*6a54128fSAndroid Build Coastguard Worker  * the enter key is needed to retype it.
196*6a54128fSAndroid Build Coastguard Worker  */
parser(void)197*6a54128fSAndroid Build Coastguard Worker void parser (void)
198*6a54128fSAndroid Build Coastguard Worker {
199*6a54128fSAndroid Build Coastguard Worker 	char *ptr,command_line [80];
200*6a54128fSAndroid Build Coastguard Worker 	int quit=0;
201*6a54128fSAndroid Build Coastguard Worker 
202*6a54128fSAndroid Build Coastguard Worker #if 0
203*6a54128fSAndroid Build Coastguard Worker 	noecho();
204*6a54128fSAndroid Build Coastguard Worker 	cbreak();
205*6a54128fSAndroid Build Coastguard Worker 	keypad(command_win, 1);
206*6a54128fSAndroid Build Coastguard Worker 	wtimeout(command_win, 100);
207*6a54128fSAndroid Build Coastguard Worker 
208*6a54128fSAndroid Build Coastguard Worker 	rl_getc_function = rl_getc_replacement;
209*6a54128fSAndroid Build Coastguard Worker #endif
210*6a54128fSAndroid Build Coastguard Worker 
211*6a54128fSAndroid Build Coastguard Worker 	while (!quit) {
212*6a54128fSAndroid Build Coastguard Worker 		/* Terminal screen size has changed */
213*6a54128fSAndroid Build Coastguard Worker 		if (redraw_request) {
214*6a54128fSAndroid Build Coastguard Worker 			redraw_all();
215*6a54128fSAndroid Build Coastguard Worker 			redraw_request=0;
216*6a54128fSAndroid Build Coastguard Worker 		}
217*6a54128fSAndroid Build Coastguard Worker 
218*6a54128fSAndroid Build Coastguard Worker 		wmove (command_win,0,0);
219*6a54128fSAndroid Build Coastguard Worker 		wclrtoeol (command_win);
220*6a54128fSAndroid Build Coastguard Worker 		wprintw (command_win,"ext2ed > ");
221*6a54128fSAndroid Build Coastguard Worker 		refresh_command_win ();
222*6a54128fSAndroid Build Coastguard Worker 
223*6a54128fSAndroid Build Coastguard Worker 		/*
224*6a54128fSAndroid Build Coastguard Worker 		 * The ncurses library optimizes cursor movement by
225*6a54128fSAndroid Build Coastguard Worker 		 * keeping track of the cursor position. However, by
226*6a54128fSAndroid Build Coastguard Worker 		 * using the readline library I'm breaking its
227*6a54128fSAndroid Build Coastguard Worker 		 * assumptions. The double -1 arguments tell ncurses
228*6a54128fSAndroid Build Coastguard Worker 		 * to disable cursor movement optimization this
229*6a54128fSAndroid Build Coastguard Worker 		 * time.
230*6a54128fSAndroid Build Coastguard Worker 		 */
231*6a54128fSAndroid Build Coastguard Worker 		mvcur (-1,-1,LINES-COMMAND_WIN_LINES,0);
232*6a54128fSAndroid Build Coastguard Worker 
233*6a54128fSAndroid Build Coastguard Worker 		/* echo (); */
234*6a54128fSAndroid Build Coastguard Worker 		ptr=readline ("ext2ed > ");
235*6a54128fSAndroid Build Coastguard Worker 		/* noecho (); */
236*6a54128fSAndroid Build Coastguard Worker 
237*6a54128fSAndroid Build Coastguard Worker 		/*
238*6a54128fSAndroid Build Coastguard Worker 		 * Readline allocated the buffer - Copy the string
239*6a54128fSAndroid Build Coastguard Worker 		 * and free the allocated buffer
240*6a54128fSAndroid Build Coastguard Worker 		 * XXX WHY???
241*6a54128fSAndroid Build Coastguard Worker 		 */
242*6a54128fSAndroid Build Coastguard Worker 		strcpy (command_line,ptr);
243*6a54128fSAndroid Build Coastguard Worker 		free (ptr);
244*6a54128fSAndroid Build Coastguard Worker 
245*6a54128fSAndroid Build Coastguard Worker 		if (*command_line != 0)
246*6a54128fSAndroid Build Coastguard Worker 			add_history (command_line);
247*6a54128fSAndroid Build Coastguard Worker 
248*6a54128fSAndroid Build Coastguard Worker 		/* If only enter was pressed, recall the last command */
249*6a54128fSAndroid Build Coastguard Worker 		if (*command_line==0)
250*6a54128fSAndroid Build Coastguard Worker 			strcpy (command_line,last_command_line);
251*6a54128fSAndroid Build Coastguard Worker 
252*6a54128fSAndroid Build Coastguard Worker 		/* Emulate readline's actions for ncurses */
253*6a54128fSAndroid Build Coastguard Worker 		mvcur (-1,-1,LINES-COMMAND_WIN_LINES,0);
254*6a54128fSAndroid Build Coastguard Worker 		werase (command_win);
255*6a54128fSAndroid Build Coastguard Worker 		wprintw (command_win,"ext2ed > ");
256*6a54128fSAndroid Build Coastguard Worker 		wprintw (command_win,command_line);
257*6a54128fSAndroid Build Coastguard Worker 		wprintw (command_win,"\n");
258*6a54128fSAndroid Build Coastguard Worker 		refresh_command_win ();
259*6a54128fSAndroid Build Coastguard Worker 
260*6a54128fSAndroid Build Coastguard Worker 		/* Save this command in our tiny cache */
261*6a54128fSAndroid Build Coastguard Worker 		strcpy (last_command_line,command_line);
262*6a54128fSAndroid Build Coastguard Worker 
263*6a54128fSAndroid Build Coastguard Worker 		/* And call dispatch to do the actual job */
264*6a54128fSAndroid Build Coastguard Worker 		quit=dispatch (command_line);
265*6a54128fSAndroid Build Coastguard Worker 	}
266*6a54128fSAndroid Build Coastguard Worker }
267*6a54128fSAndroid Build Coastguard Worker #else
read_line(char * foo)268*6a54128fSAndroid Build Coastguard Worker void read_line(char * foo) {
269*6a54128fSAndroid Build Coastguard Worker 	char * chptr = foo;
270*6a54128fSAndroid Build Coastguard Worker 	int ch;
271*6a54128fSAndroid Build Coastguard Worker 	int done = 0;
272*6a54128fSAndroid Build Coastguard Worker 
273*6a54128fSAndroid Build Coastguard Worker 	while (!done && (ch = command_read_key())) {
274*6a54128fSAndroid Build Coastguard Worker 		switch (ch) {
275*6a54128fSAndroid Build Coastguard Worker 		case '\n':
276*6a54128fSAndroid Build Coastguard Worker 			done = 1;
277*6a54128fSAndroid Build Coastguard Worker 			break;
278*6a54128fSAndroid Build Coastguard Worker 
279*6a54128fSAndroid Build Coastguard Worker 		case '\b':
280*6a54128fSAndroid Build Coastguard Worker 			if (chptr > foo) {
281*6a54128fSAndroid Build Coastguard Worker 				wprintw(command_win, "\b \b");
282*6a54128fSAndroid Build Coastguard Worker 				chptr--;
283*6a54128fSAndroid Build Coastguard Worker 			}
284*6a54128fSAndroid Build Coastguard Worker 			break;
285*6a54128fSAndroid Build Coastguard Worker 
286*6a54128fSAndroid Build Coastguard Worker 		default:
287*6a54128fSAndroid Build Coastguard Worker 			if (ch > 256)
288*6a54128fSAndroid Build Coastguard Worker 				break;
289*6a54128fSAndroid Build Coastguard Worker 			if (ch == '\n') break;
290*6a54128fSAndroid Build Coastguard Worker 			*chptr++ = ch;
291*6a54128fSAndroid Build Coastguard Worker 			wprintw(command_win, "%c", ch);
292*6a54128fSAndroid Build Coastguard Worker 			break;
293*6a54128fSAndroid Build Coastguard Worker 		}
294*6a54128fSAndroid Build Coastguard Worker 	}
295*6a54128fSAndroid Build Coastguard Worker 	*chptr = '\0';
296*6a54128fSAndroid Build Coastguard Worker }
297*6a54128fSAndroid Build Coastguard Worker 
parser(void)298*6a54128fSAndroid Build Coastguard Worker void parser (void)
299*6a54128fSAndroid Build Coastguard Worker {
300*6a54128fSAndroid Build Coastguard Worker 	char command_line [80];
301*6a54128fSAndroid Build Coastguard Worker 	int quit=0;
302*6a54128fSAndroid Build Coastguard Worker 
303*6a54128fSAndroid Build Coastguard Worker 	noecho();
304*6a54128fSAndroid Build Coastguard Worker 	cbreak();
305*6a54128fSAndroid Build Coastguard Worker 	wtimeout(command_win, 100);
306*6a54128fSAndroid Build Coastguard Worker 	keypad(command_win, 1);
307*6a54128fSAndroid Build Coastguard Worker 
308*6a54128fSAndroid Build Coastguard Worker 	while (!quit) {
309*6a54128fSAndroid Build Coastguard Worker 		/* Terminal screen size has changed */
310*6a54128fSAndroid Build Coastguard Worker 		if (redraw_request) {
311*6a54128fSAndroid Build Coastguard Worker 			redraw_all();
312*6a54128fSAndroid Build Coastguard Worker 			redraw_request=0;
313*6a54128fSAndroid Build Coastguard Worker 		}
314*6a54128fSAndroid Build Coastguard Worker 
315*6a54128fSAndroid Build Coastguard Worker 		wmove (command_win,0,0);wclrtoeol (command_win);
316*6a54128fSAndroid Build Coastguard Worker 
317*6a54128fSAndroid Build Coastguard Worker 		wmove(command_win, 0, 0);
318*6a54128fSAndroid Build Coastguard Worker 		wprintw(command_win, "ext2ed > ");
319*6a54128fSAndroid Build Coastguard Worker 		read_line(command_line);
320*6a54128fSAndroid Build Coastguard Worker 
321*6a54128fSAndroid Build Coastguard Worker 		/* If only enter was pressed, recall the last command */
322*6a54128fSAndroid Build Coastguard Worker  		if (*command_line==0)
323*6a54128fSAndroid Build Coastguard Worker  			strcpy (command_line,last_command_line);
324*6a54128fSAndroid Build Coastguard Worker 
325*6a54128fSAndroid Build Coastguard Worker 		mvcur (-1,-1,LINES-COMMAND_WIN_LINES + 1,0);
326*6a54128fSAndroid Build Coastguard Worker 
327*6a54128fSAndroid Build Coastguard Worker  		strcpy (last_command_line,command_line);	/* Save this command in our tiny cache */
328*6a54128fSAndroid Build Coastguard Worker 
329*6a54128fSAndroid Build Coastguard Worker 		/* And call dispatch to do the actual job */
330*6a54128fSAndroid Build Coastguard Worker 		quit=dispatch (command_line);
331*6a54128fSAndroid Build Coastguard Worker 	}
332*6a54128fSAndroid Build Coastguard Worker }
333*6a54128fSAndroid Build Coastguard Worker #endif
334*6a54128fSAndroid Build Coastguard Worker 
335*6a54128fSAndroid Build Coastguard Worker 
336*6a54128fSAndroid Build Coastguard Worker /*
337*6a54128fSAndroid Build Coastguard Worker  * This is a very important function. Its task is to receive a command
338*6a54128fSAndroid Build Coastguard Worker  * name and link it to a C function.  There are three types of commands:
339*6a54128fSAndroid Build Coastguard Worker  *
340*6a54128fSAndroid Build Coastguard Worker  * 1.	General commands - Always available and accessed through
341*6a54128fSAndroid Build Coastguard Worker  * general_commands.
342*6a54128fSAndroid Build Coastguard Worker  * 2.	Ext2 specific commands - Available when editing an ext2
343*6a54128fSAndroid Build Coastguard Worker  * filesystem, accessed through ext2_commands.
344*6a54128fSAndroid Build Coastguard Worker  * 3.	Type specific commands - Those are changing according to the
345*6a54128fSAndroid Build Coastguard Worker  * current type. The global variable current_type points to the
346*6a54128fSAndroid Build Coastguard Worker  * current object definition (of type struct_descriptor). In it, the
347*6a54128fSAndroid Build Coastguard Worker  * struct_commands entry contains the type specific commands links.
348*6a54128fSAndroid Build Coastguard Worker  *
349*6a54128fSAndroid Build Coastguard Worker  * Overriding is an important feature - Much like in C++ : The same
350*6a54128fSAndroid Build Coastguard Worker  * command name can dispatch to different functions. The overriding
351*6a54128fSAndroid Build Coastguard Worker  * priority is 3,2,1; That is - A type specific command will always
352*6a54128fSAndroid Build Coastguard Worker  * override a general command. This is used through the program to
353*6a54128fSAndroid Build Coastguard Worker  * allow fine tuned operation.
354*6a54128fSAndroid Build Coastguard Worker  *
355*6a54128fSAndroid Build Coastguard Worker  * When an handling function is found, it is called along with the
356*6a54128fSAndroid Build Coastguard Worker  * command line that was passed to us. The handling function is then
357*6a54128fSAndroid Build Coastguard Worker  * free to interpret the arguments in its own style.
358*6a54128fSAndroid Build Coastguard Worker  */
dispatch(char * command_line)359*6a54128fSAndroid Build Coastguard Worker int dispatch (char *command_line)
360*6a54128fSAndroid Build Coastguard Worker {
361*6a54128fSAndroid Build Coastguard Worker 	int i,found=0;
362*6a54128fSAndroid Build Coastguard Worker 
363*6a54128fSAndroid Build Coastguard Worker 	char command [80];
364*6a54128fSAndroid Build Coastguard Worker 
365*6a54128fSAndroid Build Coastguard Worker 	parse_word (command_line,command);
366*6a54128fSAndroid Build Coastguard Worker 
367*6a54128fSAndroid Build Coastguard Worker 	if (strcasecmp (command,"quit")==0) return (1);
368*6a54128fSAndroid Build Coastguard Worker 
369*6a54128fSAndroid Build Coastguard Worker 	/* 1. Search for type specific commands FIRST - Allows
370*6a54128fSAndroid Build Coastguard Worker 	overriding of a general command */
371*6a54128fSAndroid Build Coastguard Worker 
372*6a54128fSAndroid Build Coastguard Worker 	if (current_type != NULL)
373*6a54128fSAndroid Build Coastguard Worker 		for (i=0;
374*6a54128fSAndroid Build Coastguard Worker 		     i<=current_type->type_commands.last_command && !found;
375*6a54128fSAndroid Build Coastguard Worker 		     i++) {
376*6a54128fSAndroid Build Coastguard Worker 			if (strcasecmp (command,current_type->type_commands.names [i])==0) {
377*6a54128fSAndroid Build Coastguard Worker 				(*current_type->type_commands.callback [i]) (command_line);
378*6a54128fSAndroid Build Coastguard Worker 				found=1;
379*6a54128fSAndroid Build Coastguard Worker 			}
380*6a54128fSAndroid Build Coastguard Worker 		}
381*6a54128fSAndroid Build Coastguard Worker 
382*6a54128fSAndroid Build Coastguard Worker 	/* 2. Now search for ext2 filesystem general commands */
383*6a54128fSAndroid Build Coastguard Worker 
384*6a54128fSAndroid Build Coastguard Worker 	if (!found)
385*6a54128fSAndroid Build Coastguard Worker 		for (i=0;i<=ext2_commands.last_command && !found;i++) {
386*6a54128fSAndroid Build Coastguard Worker 			if (strcasecmp (command,ext2_commands.names [i])==0) {
387*6a54128fSAndroid Build Coastguard Worker 				(*ext2_commands.callback [i]) (command_line);
388*6a54128fSAndroid Build Coastguard Worker 				found=1;
389*6a54128fSAndroid Build Coastguard Worker 			}
390*6a54128fSAndroid Build Coastguard Worker 		}
391*6a54128fSAndroid Build Coastguard Worker 
392*6a54128fSAndroid Build Coastguard Worker 
393*6a54128fSAndroid Build Coastguard Worker 	/* 3. If not found, search the general commands */
394*6a54128fSAndroid Build Coastguard Worker 
395*6a54128fSAndroid Build Coastguard Worker 	if (!found)
396*6a54128fSAndroid Build Coastguard Worker 		for (i=0;i<=general_commands.last_command && !found;i++) {
397*6a54128fSAndroid Build Coastguard Worker 			if (strcasecmp (command,general_commands.names [i])==0) {
398*6a54128fSAndroid Build Coastguard Worker 				(*general_commands.callback [i]) (command_line);
399*6a54128fSAndroid Build Coastguard Worker 				found=1;
400*6a54128fSAndroid Build Coastguard Worker 			}
401*6a54128fSAndroid Build Coastguard Worker 		}
402*6a54128fSAndroid Build Coastguard Worker 
403*6a54128fSAndroid Build Coastguard Worker 	/* 4. If not found, issue an error message and return */
404*6a54128fSAndroid Build Coastguard Worker 
405*6a54128fSAndroid Build Coastguard Worker 	if (!found) {
406*6a54128fSAndroid Build Coastguard Worker 		wprintw (command_win,"Error: Unknown command\n");
407*6a54128fSAndroid Build Coastguard Worker 		refresh_command_win ();
408*6a54128fSAndroid Build Coastguard Worker 	}
409*6a54128fSAndroid Build Coastguard Worker 
410*6a54128fSAndroid Build Coastguard Worker 	return (0);
411*6a54128fSAndroid Build Coastguard Worker }
412*6a54128fSAndroid Build Coastguard Worker 
413*6a54128fSAndroid Build Coastguard Worker 
414*6a54128fSAndroid Build Coastguard Worker /*
415*6a54128fSAndroid Build Coastguard Worker  *
416*6a54128fSAndroid Build Coastguard Worker  * This function copies the next word in source to the variable dest,
417*6a54128fSAndroid Build Coastguard Worker  * ignoring whitespaces.  It returns a pointer to the next word in
418*6a54128fSAndroid Build Coastguard Worker  * source.  It is used to split the command line into command and arguments.
419*6a54128fSAndroid Build Coastguard Worker  */
parse_word(char * source,char * dest)420*6a54128fSAndroid Build Coastguard Worker char *parse_word (char *source,char *dest)
421*6a54128fSAndroid Build Coastguard Worker {
422*6a54128fSAndroid Build Coastguard Worker 	char ch,*source_ptr,*target_ptr;
423*6a54128fSAndroid Build Coastguard Worker 
424*6a54128fSAndroid Build Coastguard Worker 	if (*source==0) {
425*6a54128fSAndroid Build Coastguard Worker 		*dest=0;
426*6a54128fSAndroid Build Coastguard Worker 		return (source);
427*6a54128fSAndroid Build Coastguard Worker 	};
428*6a54128fSAndroid Build Coastguard Worker 
429*6a54128fSAndroid Build Coastguard Worker 	source_ptr=source;target_ptr=dest;
430*6a54128fSAndroid Build Coastguard Worker 	do {
431*6a54128fSAndroid Build Coastguard Worker 		ch=*source_ptr++;
432*6a54128fSAndroid Build Coastguard Worker 	} while (! (ch>' ' && ch<='z') && ch!=0);
433*6a54128fSAndroid Build Coastguard Worker 
434*6a54128fSAndroid Build Coastguard Worker 	while (ch>' ' && ch<='z') {
435*6a54128fSAndroid Build Coastguard Worker 		*target_ptr++=ch;
436*6a54128fSAndroid Build Coastguard Worker 		ch=*source_ptr++;
437*6a54128fSAndroid Build Coastguard Worker 	}
438*6a54128fSAndroid Build Coastguard Worker 
439*6a54128fSAndroid Build Coastguard Worker 	*target_ptr=0;
440*6a54128fSAndroid Build Coastguard Worker 
441*6a54128fSAndroid Build Coastguard Worker 	source_ptr--;
442*6a54128fSAndroid Build Coastguard Worker 	do {
443*6a54128fSAndroid Build Coastguard Worker 		ch=*source_ptr++;
444*6a54128fSAndroid Build Coastguard Worker 	} while (! (ch>' ' && ch<='z') && ch!=0);
445*6a54128fSAndroid Build Coastguard Worker 
446*6a54128fSAndroid Build Coastguard Worker 	return (--source_ptr);
447*6a54128fSAndroid Build Coastguard Worker }
448*6a54128fSAndroid Build Coastguard Worker 
449*6a54128fSAndroid Build Coastguard Worker /*
450*6a54128fSAndroid Build Coastguard Worker  * text is the partial command entered by the user; We assume that it
451*6a54128fSAndroid Build Coastguard Worker  * is a part of a command - I didn't write code for smarter completion.
452*6a54128fSAndroid Build Coastguard Worker  *
453*6a54128fSAndroid Build Coastguard Worker  * The state variable is an index which tells us how many possible
454*6a54128fSAndroid Build Coastguard Worker  * completions we already returned to readline.
455*6a54128fSAndroid Build Coastguard Worker  *
456*6a54128fSAndroid Build Coastguard Worker  * We return only one possible completion or (char *) NULL if there
457*6a54128fSAndroid Build Coastguard Worker  * are no more completions. This function will be called by readline
458*6a54128fSAndroid Build Coastguard Worker  * over and over until we tell it to stop.
459*6a54128fSAndroid Build Coastguard Worker  *
460*6a54128fSAndroid Build Coastguard Worker  * While scanning for possible completions, we use the same priority
461*6a54128fSAndroid Build Coastguard Worker  * definition which was used in dispatch.
462*6a54128fSAndroid Build Coastguard Worker  */
463*6a54128fSAndroid Build Coastguard Worker #if HAVE_READLINE
complete_command(char * text,int state)464*6a54128fSAndroid Build Coastguard Worker char *complete_command (char *text,int state)
465*6a54128fSAndroid Build Coastguard Worker {
466*6a54128fSAndroid Build Coastguard Worker 	int state_index=-1;
467*6a54128fSAndroid Build Coastguard Worker 	int i,len;
468*6a54128fSAndroid Build Coastguard Worker 
469*6a54128fSAndroid Build Coastguard Worker 	len=strlen (text);
470*6a54128fSAndroid Build Coastguard Worker 
471*6a54128fSAndroid Build Coastguard Worker 	/* Is the command type specific ? */
472*6a54128fSAndroid Build Coastguard Worker 
473*6a54128fSAndroid Build Coastguard Worker 	if (current_type != NULL)
474*6a54128fSAndroid Build Coastguard Worker 		for (i=0;i<=current_type->type_commands.last_command;i++) {
475*6a54128fSAndroid Build Coastguard Worker 			if (strncmp (current_type->type_commands.names [i],text,len)==0) {
476*6a54128fSAndroid Build Coastguard Worker 				state_index++;
477*6a54128fSAndroid Build Coastguard Worker 				if (state==state_index) {
478*6a54128fSAndroid Build Coastguard Worker 					return (dupstr (current_type->type_commands.names [i]));
479*6a54128fSAndroid Build Coastguard Worker 				}
480*6a54128fSAndroid Build Coastguard Worker 			}
481*6a54128fSAndroid Build Coastguard Worker 		}
482*6a54128fSAndroid Build Coastguard Worker 
483*6a54128fSAndroid Build Coastguard Worker 	/* No, perhaps ext2 specific command then ? */
484*6a54128fSAndroid Build Coastguard Worker 
485*6a54128fSAndroid Build Coastguard Worker 	for (i=0;i<=ext2_commands.last_command;i++) {
486*6a54128fSAndroid Build Coastguard Worker 		if (strncmp (ext2_commands.names [i],text,len)==0) {
487*6a54128fSAndroid Build Coastguard Worker 			state_index++;
488*6a54128fSAndroid Build Coastguard Worker 			if (state==state_index)
489*6a54128fSAndroid Build Coastguard Worker 			return (dupstr (ext2_commands.names [i]));
490*6a54128fSAndroid Build Coastguard Worker 		}
491*6a54128fSAndroid Build Coastguard Worker 	}
492*6a54128fSAndroid Build Coastguard Worker 
493*6a54128fSAndroid Build Coastguard Worker 
494*6a54128fSAndroid Build Coastguard Worker 	/* Check for a general command */
495*6a54128fSAndroid Build Coastguard Worker 
496*6a54128fSAndroid Build Coastguard Worker 	for (i=0;i<=general_commands.last_command;i++) {
497*6a54128fSAndroid Build Coastguard Worker 		if (strncmp (general_commands.names [i],text,len)==0) {
498*6a54128fSAndroid Build Coastguard Worker 				state_index++;
499*6a54128fSAndroid Build Coastguard Worker 				if (state==state_index)
500*6a54128fSAndroid Build Coastguard Worker 					return (dupstr (general_commands.names [i]));
501*6a54128fSAndroid Build Coastguard Worker 		}
502*6a54128fSAndroid Build Coastguard Worker 	}
503*6a54128fSAndroid Build Coastguard Worker 
504*6a54128fSAndroid Build Coastguard Worker 	/* quit is handled differently */
505*6a54128fSAndroid Build Coastguard Worker 
506*6a54128fSAndroid Build Coastguard Worker 	if (strncmp ("quit",text,len)==0) {
507*6a54128fSAndroid Build Coastguard Worker 		state_index++;
508*6a54128fSAndroid Build Coastguard Worker 		if (state==state_index)
509*6a54128fSAndroid Build Coastguard Worker 			return (dupstr ("quit"));
510*6a54128fSAndroid Build Coastguard Worker 	}
511*6a54128fSAndroid Build Coastguard Worker 
512*6a54128fSAndroid Build Coastguard Worker 	/* No more completions */
513*6a54128fSAndroid Build Coastguard Worker 
514*6a54128fSAndroid Build Coastguard Worker 	return ((char *) NULL);
515*6a54128fSAndroid Build Coastguard Worker }
516*6a54128fSAndroid Build Coastguard Worker #endif
517*6a54128fSAndroid Build Coastguard Worker 
518*6a54128fSAndroid Build Coastguard Worker 
519*6a54128fSAndroid Build Coastguard Worker /*
520*6a54128fSAndroid Build Coastguard Worker  * Nothing special - Just allocates enough space and copy the string.
521*6a54128fSAndroid Build Coastguard Worker  */
dupstr(char * src)522*6a54128fSAndroid Build Coastguard Worker char *dupstr (char *src)
523*6a54128fSAndroid Build Coastguard Worker {
524*6a54128fSAndroid Build Coastguard Worker 	char *ptr;
525*6a54128fSAndroid Build Coastguard Worker 
526*6a54128fSAndroid Build Coastguard Worker 	ptr=(char *) malloc (strlen (src)+1);
527*6a54128fSAndroid Build Coastguard Worker 	if (!ptr)
528*6a54128fSAndroid Build Coastguard Worker 		return NULL;
529*6a54128fSAndroid Build Coastguard Worker 	strcpy (ptr,src);
530*6a54128fSAndroid Build Coastguard Worker 	return (ptr);
531*6a54128fSAndroid Build Coastguard Worker }
532*6a54128fSAndroid Build Coastguard Worker 
533*6a54128fSAndroid Build Coastguard Worker #ifdef DEBUG
534*6a54128fSAndroid Build Coastguard Worker /*
535*6a54128fSAndroid Build Coastguard Worker  * This function reports an internal error. It is almost not used. One
536*6a54128fSAndroid Build Coastguard Worker  * place in which I do check for internal errors is disk.c.
537*6a54128fSAndroid Build Coastguard Worker  *
538*6a54128fSAndroid Build Coastguard Worker  * We just report the error, and try to continue ...
539*6a54128fSAndroid Build Coastguard Worker  */
internal_error(char * description,char * source_name,char * function_name)540*6a54128fSAndroid Build Coastguard Worker void internal_error (char *description,char *source_name,char *function_name)
541*6a54128fSAndroid Build Coastguard Worker {
542*6a54128fSAndroid Build Coastguard Worker 	wprintw (command_win,"Internal error - Found by source: %s.c , function: %s\n",source_name,function_name);
543*6a54128fSAndroid Build Coastguard Worker 	wprintw (command_win,"\t%s\n",description);
544*6a54128fSAndroid Build Coastguard Worker 	wprintw (command_win,"Press enter to (hopefully) continue\n");
545*6a54128fSAndroid Build Coastguard Worker 	refresh_command_win ();getch ();werase (command_win);
546*6a54128fSAndroid Build Coastguard Worker }
547*6a54128fSAndroid Build Coastguard Worker 
548*6a54128fSAndroid Build Coastguard Worker #endif
549