e2fsprogs/ext2ed/general_com.c
Theodore Ts'o 5e941d2979 Fix up ncurses interface so that it handles resizes correctly.
Removed the readline library (still available using if HAVE_READLINE is defined)
since it really doesn't play well with ncurses.  The only real feature it added 
was command completion, and it didn't really handle it completely correctly anyway.
(If readline printed a completion list, it completely screwed up the screen.)

We now use the wgetch ncurses interface to get input; this allows the PGDN and PGUP
keys to work correctly, and also helped fix up the resizing logic.
2002-05-13 07:53:11 -04:00

907 lines
20 KiB
C

/*
/usr/src/ext2ed/general_com.c
A part of the extended file system 2 disk editor.
---------------------
General user commands
---------------------
First written on: April 9 1995
Copyright (C) 1995 Gadi Oxman
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ext2ed.h"
#include "../version.h"
void help (char *command_line)
{
int i,max_line=0;
char argument [80],*ptr;
werase (show_pad);wmove (show_pad,0,0);
ptr=parse_word (command_line,argument);
if (*ptr!=0) {
ptr=parse_word (ptr,argument);
if (*argument!=0) {
detailed_help (argument);
return;
}
}
if (current_type!=NULL) {
wprintw (show_pad,"Type %s specific commands:\n",current_type->name);max_line++;
if (current_type->type_commands.last_command==-1) {
wprintw (show_pad,"\nnone\n");max_line+=2;
}
else
for (i=0;i<=current_type->type_commands.last_command;i++) {
if (i%5==0) {
wprintw (show_pad,"\n");max_line++;
}
wprintw (show_pad,"%-13s",current_type->type_commands.names [i]);
if (i%5!=4)
wprintw (show_pad,"; ");
}
wprintw (show_pad,"\n\n");max_line+=2;
}
if (ext2_commands.last_command != -1) {
wprintw (show_pad,"ext2 filesystem general commands: \n");max_line++;
for (i=0;i<=ext2_commands.last_command;i++) {
if (i%5==0) {
wprintw (show_pad,"\n");max_line++;
}
wprintw (show_pad,"%-13s",ext2_commands.names [i]);
if (i%5!=4)
wprintw (show_pad,"; ");
}
wprintw (show_pad,"\n\n");max_line+=2;
}
wprintw (show_pad,"General commands: \n");
for (i=0;i<=general_commands.last_command;i++) {
if (i%5==0) {
wprintw (show_pad,"\n");max_line++;
}
wprintw (show_pad,"%-13s",general_commands.names [i]);
if (i%5!=4)
wprintw (show_pad,"; ");
}
wprintw (show_pad,"\n\n");max_line+=2;
wprintw (show_pad,"EXT2ED ver %s (%s)\n",E2FSPROGS_VERSION, E2FSPROGS_DATE);
wprintw (show_pad,"Copyright (C) 1995 Gadi Oxman\n");
wprintw (show_pad,"Reviewed 2001 Christian Bac\n");
wprintw (show_pad,"Modified and enchanced by Theodore Ts'o, 2002\n");
wprintw (show_pad,"EXT2ED is hereby placed under the terms of the GNU General Public License.\n\n");
wprintw (show_pad,"EXT2ED was programmed as a student project in the software laboratory\n");
wprintw (show_pad,"of the faculty of electrical engineering in the\n");
wprintw (show_pad,"Technion - Israel Institute of Technology\n");
wprintw (show_pad,"with the guide of Avner Lottem and Dr. Ilana David.\n");
max_line+=10;
show_pad_info.line=0;show_pad_info.max_line=max_line;
werase (show_win);wmove (show_win,0,0);
wprintw (show_win,"EXT2ED help");
refresh_show_win ();
refresh_show_pad ();
}
void detailed_help (char *text)
{
int i;
if (current_type != NULL)
for (i=0;i<=current_type->type_commands.last_command;i++) {
if (strcmp (current_type->type_commands.names [i],text)==0) {
wprintw (show_pad,"%s - %s\n",text,current_type->type_commands.descriptions [i]);
refresh_show_pad ();return;
}
}
for (i=0;i<=ext2_commands.last_command;i++) {
if (strcmp (ext2_commands.names [i],text)==0) {
wprintw (show_pad,"%s - %s\n",text,ext2_commands.descriptions [i]);
refresh_show_pad ();return;
}
}
for (i=0;i<=general_commands.last_command;i++) {
if (strcmp (general_commands.names [i],text)==0) {
wprintw (show_pad,"%s - %s\n",text,general_commands.descriptions [i]);
refresh_show_pad ();return;
}
}
if (strcmp ("quit",text)==0) {
wprintw (show_pad,"quit - Exists EXT2ED");
refresh_show_pad ();return;
}
wprintw (show_pad,"Error - Command %s not aviable now\n",text);
refresh_show_pad ();return;
}
void set_device (char *command_line)
{
char *ptr,new_device [80];
ptr=parse_word (command_line,new_device);
if (*ptr==0) {
wprintw (command_win,"Error - Device name not specified\n");
refresh_command_win ();return;
}
parse_word (ptr,new_device);
check_mounted (new_device);
if (mounted && !AllowMountedRead) {
wprintw (command_win,"Error - Filesystem is mounted, aborting\n");
wprintw (command_win,"You may wish to use the AllowMountedRead on configuration option\n");
refresh_command_win ();return;
}
if (mounted && AllowMountedRead) {
wprintw (command_win,"Warning - Filesystem is mounted. Displayed data may be unreliable.\n");
refresh_command_win ();
}
if (device_handle!=NULL)
fclose (device_handle);
if ( (device_handle=fopen (new_device,"rb"))==NULL) {
wprintw (command_win,"Error - Can not open device %s\n",new_device);refresh_command_win ();
return;
}
else {
strcpy (device_name,new_device);
write_access=0; /* Write access disabled */
current_type=NULL; /* There is no type now */
remember_lifo.entries_count=0; /* Empty Object memory */
free_user_commands (&ext2_commands); /* Free filesystem specific objects */
free_struct_descriptors ();
if (!set_file_system_info ()) { /* Error while getting info --> abort */
free_user_commands (&ext2_commands);
free_struct_descriptors ();
fclose (device_handle);
device_handle=NULL; /* Notice that our device is still not set up */
device_offset=-1;
return;
}
if (*AlternateDescriptors) /* Check if user defined objects exist */
set_struct_descriptors (AlternateDescriptors);
dispatch ("setoffset 0");
dispatch ("help"); /* Show help screen */
wprintw (command_win,"Device changed to %s",device_name);refresh_command_win ();
}
}
void set_offset (char *command_line)
{
long mult=1;
long new_offset;
char *ptr,new_offset_buffer [80];
if (device_handle==NULL) {
wprintw (command_win,"Error - No device opened\n");refresh_command_win ();
return;
}
ptr=parse_word (command_line,new_offset_buffer);
if (*ptr==0) {
wprintw (command_win,"Error - No argument specified\n");refresh_command_win ();
return;
}
ptr=parse_word (ptr,new_offset_buffer);
if (strcmp (new_offset_buffer,"block")==0) {
mult=file_system_info.block_size;
ptr=parse_word (ptr,new_offset_buffer);
}
if (strcmp (new_offset_buffer,"type")==0) {
if (current_type==NULL) {
wprintw (command_win,"Error - No type set\n");refresh_command_win ();
return;
}
mult=current_type->length;
ptr=parse_word (ptr,new_offset_buffer);
}
if (*new_offset_buffer==0) {
wprintw (command_win,"Error - No offset specified\n");refresh_command_win ();
return;
}
if (new_offset_buffer [0]=='+') {
if (device_offset==-1) {
wprintw (command_win,"Error - Select a fixed offset first\n");refresh_command_win ();
return;
}
new_offset=device_offset+atol (new_offset_buffer+1)*mult;
}
else if (new_offset_buffer [0]=='-') {
if (device_offset==-1) {
wprintw (command_win,"Error - Select a fixed offset first\n");refresh_command_win ();
return;
}
new_offset=device_offset-atol (new_offset_buffer+1)*mult;
if (new_offset<0) new_offset=0;
}
else
new_offset=atol (new_offset_buffer)*mult;
if ( (fseek (device_handle,new_offset,SEEK_SET))==-1) {
wprintw (command_win,"Error - Failed to seek to offset %ld in device %s\n",new_offset,device_name);
refresh_command_win ();
return;
};
device_offset=new_offset;
wprintw (command_win,"Device offset changed to %ld\n",device_offset);refresh_command_win ();
load_type_data ();
type_data.offset_in_block=0;
}
void set_int(short len, void *ptr, char *name, char *value)
{
char *char_ptr;
short *short_ptr;
long *long_ptr;
long v;
char *tmp;
v = strtol(value, &tmp, 0);
if (*tmp) {
wprintw( command_win, "Bad value - %s\n", value);
return;
}
switch (len) {
case 1:
char_ptr = (char *) ptr;
*char_ptr = v;
break;
case 2:
short_ptr = (short *) ptr;
*short_ptr = v;
break;
case 4:
long_ptr = (long *) ptr;
*long_ptr = v;
break;
default:
wprintw (command_win,
"set_int: unsupported length: %d\n", len);
return;
}
wprintw (command_win, "Variable %s set to %s\n",
name, value);
}
void set_uint(short len, void *ptr, char *name, char *value)
{
unsigned char *char_ptr;
unsigned short *short_ptr;
unsigned long *long_ptr;
unsigned long v;
char *tmp;
v = strtoul(value, &tmp, 0);
if (*tmp) {
wprintw( command_win, "Bad value - %s\n", value);
return;
}
switch (len) {
case 1:
char_ptr = (unsigned char *) ptr;
*char_ptr = v;
break;
case 2:
short_ptr = (unsigned short *) ptr;
*short_ptr = v;
break;
case 4:
long_ptr = (unsigned long *) ptr;
*long_ptr = v;
break;
default:
wprintw (command_win,
"set_uint: unsupported length: %d\n", len);
return;
}
wprintw (command_win, "Variable %s set to %s\n",
name, value);
}
void set_char(short len, void *ptr, char *name, char *value)
{
if (strlen(value)+1 > len) {
wprintw( command_win, "Value %s too big for field\n",
name, len);
return;
}
memset(ptr, 0, len);
strcpy((char *) ptr, value);
wprintw (command_win, "Variable %s set to %s\n",
name, value);
}
void set (char *command_line)
{
unsigned short *int_ptr;
unsigned char *char_ptr;
unsigned long *long_ptr,offset=0;
int i,len, found=0;
char *ptr,buffer [80],variable [80],value [80];
if (device_handle==NULL) {
wprintw (command_win,"Error - No device opened\n");refresh_command_win ();
return;
}
if (current_type==NULL) {
hex_set (command_line);
return;
}
ptr=parse_word (command_line,buffer);
if (ptr==NULL || *ptr==0) {
wprintw (command_win,"Error - Missing arguments\n");refresh_command_win ();
return;
}
parse_word (ptr,buffer);
ptr=strchr (buffer,'=');
if (ptr==NULL) {
wprintw (command_win,"Error - Bad syntax\n");refresh_command_win ();return;
}
strncpy (variable,buffer,ptr-buffer);variable [ptr-buffer]=0;
strcpy (value,++ptr);
if (current_type==NULL) {
wprintw (command_win,"Sorry, not yet supported\n");refresh_command_win ();return;
}
for (i=0;i<current_type->fields_num && !found;i++) {
if (strcmp (current_type->field_names [i],variable)==0) {
found=1;
ptr=type_data.u.buffer+offset;
len = current_type->field_lengths [i];
switch (current_type->field_types [i]) {
case FIELD_TYPE_INT:
set_int(len, ptr, variable, value);
break;
case FIELD_TYPE_UINT:
set_uint(len, ptr, variable, value);
break;
case FIELD_TYPE_CHAR:
set_char(len, ptr, variable, value);
break;
default:
wprintw (command_win,
"set: unhandled type %d\n",
current_type->field_types [i]);
break;
}
refresh_command_win ();
}
offset+=current_type->field_lengths [i];
}
if (found)
dispatch ("show");
else {
wprintw (command_win,"Error - Variable %s not found\n",variable);
refresh_command_win ();
}
}
void hex_set (char *command_line)
{
unsigned char tmp;
char *ptr,buffer [80],*ch_ptr;
int mode=HEX;
ptr=parse_word (command_line,buffer);
if (*ptr==0) {
wprintw (command_win,"Error - Argument not specified\n");refresh_command_win ();return;
}
ptr=parse_word (ptr,buffer);
if (strcasecmp (buffer,"text")==0) {
mode=TEXT;
strcpy (buffer,ptr);
}
else if (strcasecmp (buffer,"hex")==0) {
mode=HEX;
ptr=parse_word (ptr,buffer);
}
if (*buffer==0) {
wprintw (command_win,"Error - Data not specified\n");refresh_command_win ();return;
}
if (mode==HEX) {
do {
tmp=(unsigned char) strtol (buffer,NULL,16);
type_data.u.buffer [type_data.offset_in_block]=tmp;
type_data.offset_in_block++;
ptr=parse_word (ptr,buffer);
if (type_data.offset_in_block==file_system_info.block_size) {
if (*ptr) {
wprintw (command_win,"Error - Ending offset outside block, only partial string changed\n");
refresh_command_win ();
}
type_data.offset_in_block--;
}
} while (*buffer) ;
}
else {
ch_ptr=buffer;
while (*ch_ptr) {
tmp=(unsigned char) *ch_ptr++;
type_data.u.buffer [type_data.offset_in_block]=tmp;
type_data.offset_in_block++;
if (type_data.offset_in_block==file_system_info.block_size) {
if (*ch_ptr) {
wprintw (command_win,"Error - Ending offset outside block, only partial string changed\n");
refresh_command_win ();
}
type_data.offset_in_block--;
}
}
}
strcpy (buffer,"show");dispatch (buffer);
}
void set_type (char *command_line)
{
struct struct_descriptor *descriptor_ptr;
char *ptr,buffer [80],tmp_buffer [80];
short found=0;
if (!load_type_data ())
return;
ptr=parse_word (command_line,buffer);
parse_word (ptr,buffer);
if (strcmp (buffer,"none")==0 || strcmp (buffer,"hex")==0) {
wprintw (command_win,"Data will be shown as hex dump\n");refresh_command_win ();
current_type=NULL;
sprintf (tmp_buffer,"show");dispatch (tmp_buffer);
return;
}
descriptor_ptr=first_type;
while (descriptor_ptr!=NULL && !found) {
if (strcmp (descriptor_ptr->name,buffer)==0)
found=1;
else
descriptor_ptr=descriptor_ptr->next;
}
if (found) {
wprintw (command_win,"Structure type set to %s\n",buffer);refresh_command_win ();
current_type=descriptor_ptr;
sprintf (tmp_buffer,"show");dispatch (tmp_buffer);
}
else {
wprintw (command_win,"Error - %s is not a valid type\n",buffer);refresh_command_win ();
}
}
void show_int(short len, void *ptr)
{
long temp;
char *format;
switch (len) {
case 1:
temp = *((char *) ptr);
format = "%3d (0x%02x)\n";
break;
case 2:
temp = *((short *) ptr);
format = "%d (0x%x)\n";
break;
case 4:
temp = *((long *) ptr);
format = "%d\n";
break;
default:
wprintw (show_pad, "unimplemented\n");
return;
}
wprintw(show_pad, format, temp, temp);
}
void show_uint(short len, void *ptr)
{
unsigned long temp;
char *format;
switch (len) {
case 1:
temp = *((unsigned char *) ptr);
temp = temp & 0xFF;
format = "%3u (0x%02x)\n";
break;
case 2:
temp = *((unsigned short *) ptr);
temp = temp & 0xFFFF;
format = "%u (0x%x)\n";
break;
case 4:
temp = (unsigned long) *((unsigned long *) ptr);
format = "%u\n";
break;
default:
wprintw (show_pad, "unimplemented\n");
return;
}
wprintw(show_pad, format, temp, temp);
}
void show_char(short len, void *ptr)
{
unsigned char *cp = (unsigned char *) ptr;
unsigned char ch;
int i,j;
wprintw(show_pad, "\"");
for (i=0; i < len; i++) {
ch = *cp++;
if (ch == 0) {
for (j=i+1; j < len; j++)
if (cp[j-i])
break;
if (j == len)
break;
}
if (ch > 128) {
wprintw(show_pad, "M-");
ch -= 128;
}
if ((ch < 32) || (ch == 0x7f)) {
wprintw(show_pad, "^");
ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
}
wprintw(show_pad, "%c", ch);
}
wprintw(show_pad, "\"\n");
}
void show (char *command_line)
{
unsigned int i,l,len,temp_int;
unsigned long offset=0,temp_long;
unsigned char temp_char,*ch_ptr;
void *ptr;
if (device_handle==NULL)
return;
show_pad_info.line=0;
if (current_type==NULL) {
wmove (show_pad,0,0);
ch_ptr=type_data.u.buffer;
for (l=0;l<file_system_info.block_size/16;l++) {
wprintw (show_pad,"%08ld : ",offset);
for (i=0;i<16;i++) {
if (type_data.offset_in_block==offset+i)
wattrset (show_pad,A_REVERSE);
if (ch_ptr [i]>=' ' && ch_ptr [i]<='z')
wprintw (show_pad,"%c",ch_ptr [i]);
else
wprintw (show_pad,".");
if (type_data.offset_in_block==offset+i)
wattrset (show_pad,A_NORMAL);
}
wprintw (show_pad," ");
for (i=0;i<16;i++) {
if (type_data.offset_in_block==offset+i)
wattrset (show_pad,A_REVERSE);
wprintw (show_pad,"%02x",ch_ptr [i]);
if (type_data.offset_in_block==offset+i) {
wattrset (show_pad,A_NORMAL);
show_pad_info.line=l-l % show_pad_info.display_lines;
}
wprintw (show_pad," ");
}
wprintw (show_pad,"\n");
offset+=16;
ch_ptr+=16;
}
show_pad_info.max_line=l-1;show_pad_info.max_col=COLS-1;
refresh_show_pad ();show_info ();
}
else {
wmove (show_pad,0,0);l=0;
for (i=0;i<current_type->fields_num;i++) {
wprintw (show_pad,"%-20s = ",current_type->field_names [i]);
ptr=type_data.u.buffer+offset;
len = current_type->field_lengths[i];
switch (current_type->field_types[i]) {
case FIELD_TYPE_INT:
show_int(len, ptr);
break;
case FIELD_TYPE_UINT:
show_uint(len, ptr);
break;
case FIELD_TYPE_CHAR:
show_char(len, ptr);
break;
default:
wprintw (show_pad, "unimplemented\n");
break;
}
offset+=len;
l++;
}
current_type->length=offset;
show_pad_info.max_line=l-1;
refresh_show_pad ();show_info ();
}
}
void next (char *command_line)
{
long offset=1;
char *ptr,buffer [80];
ptr=parse_word (command_line,buffer);
if (*ptr!=0) {
ptr=parse_word (ptr,buffer);
offset*=atol (buffer);
}
if (current_type!=NULL) {
sprintf (buffer,"setoffset type +%ld",offset);
dispatch (buffer);
return;
}
if (type_data.offset_in_block+offset < file_system_info.block_size) {
type_data.offset_in_block+=offset;
sprintf (buffer,"show");dispatch (buffer);
}
else {
wprintw (command_win,"Error - Offset out of block\n");refresh_command_win ();
}
}
void prev (char *command_line)
{
long offset=1;
char *ptr,buffer [80];
ptr=parse_word (command_line,buffer);
if (*ptr!=0) {
ptr=parse_word (ptr,buffer);
offset*=atol (buffer);
}
if (current_type!=NULL) {
sprintf (buffer,"setoffset type -%ld",offset);
dispatch (buffer);
return;
}
if (type_data.offset_in_block-offset >= 0) {
type_data.offset_in_block-=offset;
sprintf (buffer,"show");dispatch (buffer);
}
else {
wprintw (command_win,"Error - Offset out of block\n");refresh_command_win ();
}
}
void pgdn (char *commnad_line)
{
show_pad_info.line+=show_pad_info.display_lines;
refresh_show_pad ();refresh_show_win ();
}
void pgup (char *command_line)
{
show_pad_info.line-=show_pad_info.display_lines;
refresh_show_pad ();refresh_show_win ();
}
void redraw (char *command_line)
{
redraw_all ();
dispatch ("show");
}
void remember (char *command_line)
{
long entry_num;
char *ptr,buffer [80];
if (device_handle==NULL) {
wprintw (command_win,"Error - No device opened\n");refresh_command_win ();
return;
}
ptr=parse_word (command_line,buffer);
if (*ptr==0) {
wprintw (command_win,"Error - Argument not specified\n");refresh_command_win ();
return;
}
ptr=parse_word (ptr,buffer);
entry_num=remember_lifo.entries_count++;
if (entry_num>REMEMBER_COUNT-1) {
entry_num=0;
remember_lifo.entries_count--;
}
remember_lifo.offset [entry_num]=device_offset;
remember_lifo.type [entry_num]=current_type;
strcpy (remember_lifo.name [entry_num],buffer);
if (current_type!=NULL)
wprintw (command_win,"Object %s in Offset %ld remembered as %s\n",current_type->name,device_offset,buffer);
else
wprintw (command_win,"Offset %ld remembered as %s\n",device_offset,buffer);
refresh_command_win ();
}
void recall (char *command_line)
{
char *ptr,buffer [80];
long entry_num;
if (device_handle==NULL) {
wprintw (command_win,"Error - No device opened\n");refresh_command_win ();
return;
}
ptr=parse_word (command_line,buffer);
if (*ptr==0) {
wprintw (command_win,"Error - Argument not specified\n");refresh_command_win ();
return;
}
ptr=parse_word (ptr,buffer);
for (entry_num=remember_lifo.entries_count-1;entry_num>=0;entry_num--) {
if (strcmp (remember_lifo.name [entry_num],buffer)==0)
break;
}
if (entry_num==-1) {
wprintw (command_win,"Error - Can not recall %s\n",buffer);refresh_command_win ();
return;
}
sprintf (buffer,"setoffset %ld",remember_lifo.offset [entry_num]);dispatch (buffer);
if (remember_lifo.type [entry_num] != NULL) {
sprintf (buffer,"settype %s",remember_lifo.type [entry_num]->name);dispatch (buffer);
}
else {
sprintf (buffer,"settype none");dispatch (buffer);
}
wprintw (command_win,"Object %s in Offset %ld recalled\n",current_type->name,device_offset);
refresh_command_win ();
}
void enable_write (char *command_line)
{
FILE *fp;
if (device_handle==NULL) {
wprintw (command_win,"Error - No device opened\n");refresh_command_win ();
return;
}
if (!AllowChanges) {
wprintw (command_win,"Sorry, write access is not allowed\n");
return;
}
if (mounted) {
wprintw (command_win,"Error - Filesystem is mounted\n");
return;
}
if ( (fp=fopen (device_name,"r+b"))==NULL) {
wprintw (command_win,"Error - Can not open device %s for reading and writing\n",device_name);refresh_command_win ();
return;
}
fclose (device_handle);
device_handle=fp;write_access=1;
wprintw (command_win,"Write access enabled - Be careful\n");refresh_command_win ();
}
void disable_write (char *command_line)
{
FILE *fp;
if (device_handle==NULL) {
wprintw (command_win,"Error - No device opened\n");refresh_command_win ();
return;
}
if ( (fp=fopen (device_name,"rb"))==NULL) {
wprintw (command_win,"Error - Can not open device %s\n",device_name);refresh_command_win ();
return;
}
fclose (device_handle);
device_handle=fp;write_access=0;
wprintw (command_win,"Write access disabled\n");refresh_command_win ();
}
void write_data (char *command_line)
{
write_type_data ();
}