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