/*
/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 "config.h"
#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 enhanced 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 available 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 ();
}