Home | History | Annotate | Download | only in ext2ed
      1 /*
      2 
      3 /usr/src/ext2ed/init.c
      4 
      5 A part of the extended file system 2 disk editor.
      6 
      7 --------------------------------
      8 Various initialization routines.
      9 --------------------------------
     10 
     11 First written on: April 9 1995
     12 
     13 Copyright (C) 1995 Gadi Oxman
     14 
     15 */
     16 
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 #include <string.h>
     20 #ifdef HAVE_READLINE
     21 #include <readline.h>
     22 #endif
     23 #include <signal.h>
     24 #include <unistd.h>
     25 
     26 #include <sys/types.h>
     27 #include <sys/stat.h>
     28 #include <fcntl.h>
     29 
     30 #include "ext2ed.h"
     31 
     32 char lines_s [80],cols_s [80];
     33 
     34 void signal_handler (void);
     35 
     36 void prepare_to_close (void)
     37 
     38 {
     39 	close_windows ();
     40 	if (device_handle!=NULL)
     41 		fclose (device_handle);
     42 	free_user_commands (&general_commands);
     43 	free_user_commands (&ext2_commands);
     44 	free_struct_descriptors ();
     45 }
     46 
     47 int init (void)
     48 
     49 {
     50 	printf ("Initializing ...\n");
     51 
     52 	if (!process_configuration_file ()) {
     53 		fprintf (stderr,"Error - Unable to complete configuration. Quitting.\n");
     54 		return (0);
     55 	};
     56 
     57 	general_commands.last_command=-1;	/* No commands whatsoever meanwhile */
     58 	ext2_commands.last_command=-1;
     59 	add_general_commands ();		/* Add the general commands, aviable always */
     60 	device_handle=NULL;			/* Notice that our device is still not set up */
     61 	device_offset=-1;
     62 	current_type=NULL;			/* No filesystem specific types yet */
     63 
     64 	remember_lifo.entries_count=0;		/* Object memory is empty */
     65 
     66 	init_windows ();			/* Initialize the NCURSES interface */
     67 	init_readline ();			/* Initialize the READLINE interface */
     68 	init_signals ();			/* Initialize the signal handlers */
     69 	write_access=0;				/* Write access disabled */
     70 
     71 	strcpy (last_command_line,"help");	/* Show the help screen to the user */
     72 	dispatch ("help");
     73 	return (1);				/* Success */
     74 }
     75 
     76 void add_general_commands (void)
     77 
     78 {
     79 	add_user_command (&general_commands,"help","EXT2ED help system",help);
     80 	add_user_command (&general_commands,"set","Changes a variable in the current object",set);
     81 	add_user_command (&general_commands,"setdevice","Selects the filesystem block device (e.g. /dev/hda1)",set_device);
     82 	add_user_command (&general_commands,"setoffset","Moves asynchronicly in the filesystem",set_offset);
     83 	add_user_command (&general_commands,"settype","Tells EXT2ED how to interpert the current object",set_type);
     84 	add_user_command (&general_commands,"show","Displays the current object",show);
     85 	add_user_command (&general_commands,"pgup","Scrolls data one page up",pgup);
     86 	add_user_command (&general_commands,"pgdn","Scrolls data one page down",pgdn);
     87 	add_user_command (&general_commands,"redraw","Redisplay the screen",redraw);
     88 	add_user_command (&general_commands,"remember","Saves the current position and data information",remember);
     89 	add_user_command (&general_commands,"recall","Gets back to the saved object position",recall);
     90 	add_user_command (&general_commands,"enablewrite","Enters Read/Write mode - Allows changing the filesystem",enable_write);
     91 	add_user_command (&general_commands,"disablewrite","Enters read only mode",disable_write);
     92 	add_user_command (&general_commands,"writedata","Write data back to disk",write_data);
     93 	add_user_command (&general_commands,"next","Moves to the next byte in hex mode",next);
     94 	add_user_command (&general_commands,"prev","Moves to the previous byte in hex mode",prev);
     95 }
     96 
     97 void add_ext2_general_commands (void)
     98 
     99 {
    100 	add_user_command (&ext2_commands,"super","Moves to the superblock of the filesystem",type_ext2___super);
    101 	add_user_command (&ext2_commands,"group","Moves to the first group descriptor",type_ext2___group);
    102 	add_user_command (&ext2_commands,"cd","Moves to the directory specified",type_ext2___cd);
    103 }
    104 
    105 int set_struct_descriptors (char *file_name)
    106 
    107 {
    108 	FILE *fp;
    109 	char current_line [500],current_word [50],*ch;
    110 	char variable_name [50],variable_type [20];
    111 	struct struct_descriptor *current_descriptor;
    112 
    113 	if ( (fp=fopen (file_name,"rt"))==NULL) {
    114 		wprintw (command_win,"Error - Failed to open descriptors file %s\n",file_name);
    115 		refresh_command_win ();	return (0);
    116 	};
    117 
    118 	while (!feof (fp)) {
    119 		fgets (current_line,500,fp);
    120 		if (feof (fp)) break;
    121 		ch=parse_word (current_line,current_word);
    122 		if (strcmp (current_word,"struct")==0) {
    123 			ch=parse_word (ch,current_word);
    124 			current_descriptor=add_new_descriptor (current_word);
    125 
    126 			while (strchr (current_line,'{')==NULL) {
    127 				fgets (current_line,500,fp);
    128 				if (feof (fp)) break;
    129 			};
    130 			if (feof (fp)) break;
    131 
    132 			fgets (current_line,500,fp);
    133 
    134 			while (strchr (current_line,'}')==NULL) {
    135 				while (strchr (current_line,';')==NULL) {
    136 					fgets (current_line,500,fp);
    137 					if (strchr (current_line,'}')!=NULL) break;
    138 				};
    139 				if (strchr (current_line,'}') !=NULL) break;
    140 				ch=parse_word (current_line,variable_type);
    141 				ch=parse_word (ch,variable_name);
    142 				while (variable_name [strlen (variable_name)-1]!=';') {
    143 					strcpy (variable_type,variable_name);
    144 					ch=parse_word (ch,variable_name);
    145 				};
    146 				variable_name [strlen (variable_name)-1]=0;
    147 				add_new_variable (current_descriptor,variable_type,variable_name);
    148 				fgets (current_line,500,fp);
    149 			};
    150 		};
    151 	};
    152 
    153 	fclose (fp);
    154 	return (1);
    155 }
    156 
    157 void free_struct_descriptors (void)
    158 
    159 {
    160 	struct struct_descriptor *ptr,*next;
    161 
    162 	ptr=first_type;
    163 	while (ptr!=NULL) {
    164 		next=ptr->next;
    165 		free_user_commands (&ptr->type_commands);
    166 		free (ptr);
    167 		ptr=next;
    168 	}
    169 	first_type=last_type=current_type=NULL;
    170 }
    171 
    172 void free_user_commands (struct struct_commands *ptr)
    173 
    174 {
    175 	int i;
    176 
    177 	for (i=0;i<=ptr->last_command;i++) {
    178 		free (ptr->names [i]);
    179 		free (ptr->descriptions [i]);
    180 	}
    181 
    182 	ptr->last_command=-1;
    183 }
    184 
    185 struct struct_descriptor *add_new_descriptor (char *name)
    186 
    187 {
    188 	struct struct_descriptor *ptr;
    189 
    190 	ptr = malloc (sizeof (struct struct_descriptor));
    191 	if (ptr == NULL) {
    192 		printf ("Error - Can not allocate memory - Quitting\n");
    193 		exit (1);
    194 	}
    195 	memset(ptr, 0, sizeof(struct struct_descriptor));
    196 	ptr->prev = ptr->next = NULL;
    197 	strcpy (ptr->name,name);
    198 	ptr->length=0;
    199 	ptr->fields_num=0;
    200 	if (first_type==NULL) {
    201 		first_type = last_type = ptr;
    202 	} else {
    203 		ptr->prev = last_type; last_type->next = ptr; last_type=ptr;
    204 	}
    205 	ptr->type_commands.last_command=-1;
    206 	fill_type_commands (ptr);
    207 	return (ptr);
    208 }
    209 
    210 struct type_table {
    211 	char 	*name;
    212 	int	field_type;
    213 	int	len;
    214 };
    215 
    216 struct type_table type_table[] = {
    217 	{ "long",   FIELD_TYPE_INT,	4 },
    218 	{ "short",  FIELD_TYPE_INT,	2 },
    219 	{ "char",   FIELD_TYPE_CHAR,	1 },
    220 	{ "__u32",  FIELD_TYPE_UINT,	4 },
    221 	{ "__s32",  FIELD_TYPE_INT,	4 },
    222 	{ "__u16",  FIELD_TYPE_UINT,	2 },
    223 	{ "__s16",  FIELD_TYPE_INT,	2 },
    224 	{ "__u8",   FIELD_TYPE_UINT,	1 },
    225 	{ "__s8",   FIELD_TYPE_INT,	1 },
    226 	{  0,       0,                  0 }
    227 };
    228 
    229 void add_new_variable (struct struct_descriptor *ptr,char *v_type,char *v_name)
    230 
    231 {
    232 	short	len=1;
    233 	char	field_type=FIELD_TYPE_INT;
    234 	struct type_table *p;
    235 
    236 	strcpy (ptr->field_names [ptr->fields_num],v_name);
    237 	ptr->field_positions [ptr->fields_num]=ptr->length;
    238 
    239 	for (p = type_table; p->name; p++) {
    240 		if (strcmp(v_type, p->name) == 0) {
    241 			len = p->len;
    242 			field_type = p->field_type;
    243 			break;
    244 		}
    245 	}
    246 	if (p->name == 0) {
    247 		if (strncmp(v_type, "char[", 5) == 0) {
    248 			len = atoi(v_type+5);
    249 			field_type = FIELD_TYPE_CHAR;
    250 		} else {
    251 			printf("Unknown type %s for field %s\n", v_type, v_name);
    252 			exit(1);
    253 		}
    254 	}
    255 
    256 	ptr->field_lengths [ptr->fields_num] = len;
    257 	ptr->field_types [ptr->fields_num] = field_type;
    258 
    259 	ptr->length+=len;
    260 	ptr->fields_num++;
    261 }
    262 
    263 void fill_type_commands (struct struct_descriptor *ptr)
    264 
    265 /*
    266 
    267 Set specific type user commands.
    268 
    269 */
    270 
    271 {
    272 
    273 	if (strcmp ((ptr->name),"file")==0) {
    274 		add_user_command (&ptr->type_commands,"show","Shows file data",type_file___show);
    275 		add_user_command (&ptr->type_commands,"inode","Returns to the inode of the current file",type_file___inode);
    276 		add_user_command (&ptr->type_commands,"display","Specifies data format - text or hex",type_file___display);
    277 		add_user_command (&ptr->type_commands,"next","Pass to next byte",type_file___next);
    278 		add_user_command (&ptr->type_commands,"prev","Pass to the previous byte",type_file___prev);
    279 		add_user_command (&ptr->type_commands,"offset","Pass to a specified byte in the current block",type_file___offset);
    280 		add_user_command (&ptr->type_commands,"nextblock","Pass to next file block",type_file___nextblock);
    281 		add_user_command (&ptr->type_commands,"prevblock","Pass to the previous file block",type_file___prevblock);
    282 		add_user_command (&ptr->type_commands,"block","Specify which file block to edit",type_file___block);
    283 		add_user_command (&ptr->type_commands,"remember","Saves the file\'s inode position for later reference",type_file___remember);
    284 		add_user_command (&ptr->type_commands,"set","Sets the current byte",type_file___set);
    285 		add_user_command (&ptr->type_commands,"writedata","Writes the current block to the disk",type_file___writedata);
    286 	}
    287 
    288 	if (strcmp ((ptr->name),"ext2_inode")==0) {
    289 		add_user_command (&ptr->type_commands,"show","Shows inode data",type_ext2_inode___show);
    290 		add_user_command (&ptr->type_commands,"next","Move to next inode in current block group",type_ext2_inode___next);
    291 		add_user_command (&ptr->type_commands,"prev","Move to next inode in current block group",type_ext2_inode___prev);
    292 		add_user_command (&ptr->type_commands,"group","Move to the group descriptors of the current inode table",type_ext2_inode___group);
    293 		add_user_command (&ptr->type_commands,"entry","Move to a specified entry in the current inode table",type_ext2_inode___entry);
    294 		add_user_command (&ptr->type_commands,"file","Display file data of the current inode",type_ext2_inode___file);
    295 		add_user_command (&ptr->type_commands,"dir","Display directory data of the current inode",type_ext2_inode___dir);
    296 	}
    297 
    298 	if (strcmp ((ptr->name),"dir")==0) {
    299 		add_user_command (&ptr->type_commands,"show","Shows current directory data",type_dir___show);
    300 		add_user_command (&ptr->type_commands,"inode","Returns to the inode of the current directory",type_dir___inode);
    301 		add_user_command (&ptr->type_commands,"next","Pass to the next directory entry",type_dir___next);
    302 		add_user_command (&ptr->type_commands,"prev","Pass to the previous directory entry",type_dir___prev);
    303 		add_user_command (&ptr->type_commands,"followinode","Follows the inode specified in this directory entry",type_dir___followinode);
    304 		add_user_command (&ptr->type_commands,"remember","Remember the inode of the current directory entry",type_dir___remember);
    305 		add_user_command (&ptr->type_commands,"cd","Changes directory relative to the current directory",type_dir___cd);
    306 		add_user_command (&ptr->type_commands,"entry","Moves to a specified entry in the current directory",type_dir___entry);
    307 		add_user_command (&ptr->type_commands,"writedata","Writes the current entry to the disk",type_dir___writedata);
    308 		add_user_command (&ptr->type_commands,"set","Changes a variable in the current directory entry",type_dir___set);
    309 	}
    310 
    311 	if (strcmp ((ptr->name),"ext2_super_block")==0) {
    312 		add_user_command (&ptr->type_commands,"show","Displays the super block data",type_ext2_super_block___show);
    313 		add_user_command (&ptr->type_commands,"gocopy","Move to another backup copy of the superblock",type_ext2_super_block___gocopy);
    314 		add_user_command (&ptr->type_commands,"setactivecopy","Copies the current superblock to the main superblock",type_ext2_super_block___setactivecopy);
    315 	}
    316 
    317 	if (strcmp ((ptr->name),"ext2_group_desc")==0) {
    318 		add_user_command (&ptr->type_commands,"next","Pass to the next block group decriptor",type_ext2_group_desc___next);
    319 		add_user_command (&ptr->type_commands,"prev","Pass to the previous group descriptor",type_ext2_group_desc___prev);
    320 		add_user_command (&ptr->type_commands,"entry","Pass to a specific group descriptor",type_ext2_group_desc___entry);
    321 		add_user_command (&ptr->type_commands,"show","Shows the current group descriptor",type_ext2_group_desc___show);
    322 		add_user_command (&ptr->type_commands,"inode","Pass to the inode table of the current group block",type_ext2_group_desc___inode);
    323 		add_user_command (&ptr->type_commands,"gocopy","Move to another backup copy of the group descriptor",type_ext2_group_desc___gocopy);
    324 		add_user_command (&ptr->type_commands,"blockbitmap","Show the block allocation bitmap of the current group block",type_ext2_group_desc___blockbitmap);
    325 		add_user_command (&ptr->type_commands,"inodebitmap","Show the inode allocation bitmap of the current group block",type_ext2_group_desc___inodebitmap);
    326 		add_user_command (&ptr->type_commands,"setactivecopy","Copies the current group descriptor to the main table",type_ext2_super_block___setactivecopy);
    327 	}
    328 
    329 	if (strcmp ((ptr->name),"block_bitmap")==0) {
    330 		add_user_command (&ptr->type_commands,"show","Displays the block allocation bitmap",type_ext2_block_bitmap___show);
    331 		add_user_command (&ptr->type_commands,"entry","Moves to a specific bit",type_ext2_block_bitmap___entry);
    332 		add_user_command (&ptr->type_commands,"next","Moves to the next bit",type_ext2_block_bitmap___next);
    333 		add_user_command (&ptr->type_commands,"prev","Moves to the previous bit",type_ext2_block_bitmap___prev);
    334 		add_user_command (&ptr->type_commands,"allocate","Allocates the current block",type_ext2_block_bitmap___allocate);
    335 		add_user_command (&ptr->type_commands,"deallocate","Deallocates the current block",type_ext2_block_bitmap___deallocate);
    336 	}
    337 
    338 	if (strcmp ((ptr->name),"inode_bitmap")==0) {
    339 		add_user_command (&ptr->type_commands,"show","Displays the inode allocation bitmap",type_ext2_inode_bitmap___show);
    340 		add_user_command (&ptr->type_commands,"entry","Moves to a specific bit",type_ext2_inode_bitmap___entry);
    341 		add_user_command (&ptr->type_commands,"next","Moves to the next bit",type_ext2_inode_bitmap___next);
    342 		add_user_command (&ptr->type_commands,"prev","Moves to the previous bit",type_ext2_inode_bitmap___prev);
    343 		add_user_command (&ptr->type_commands,"allocate","Allocates the current inode",type_ext2_inode_bitmap___allocate);
    344 		add_user_command (&ptr->type_commands,"deallocate","Deallocates the current inode",type_ext2_inode_bitmap___deallocate);
    345 	}
    346 
    347 }
    348 
    349 void add_user_command (struct struct_commands *ptr,char *name,char *description,PF callback)
    350 
    351 {
    352 	int num;
    353 
    354 	num=ptr->last_command;
    355 	if (num+1==MAX_COMMANDS_NUM) {
    356 		printf ("Internal Error - Can't add command %s\n",name);
    357 		return;
    358 	}
    359 
    360 	ptr->last_command=++num;
    361 
    362 	ptr->names [num]=(char *) malloc (strlen (name)+1);
    363 	strcpy (ptr->names [num],name);
    364 
    365 	if (*description!=0) {
    366 		ptr->descriptions [num]=(char *) malloc (strlen (description)+1);
    367 		strcpy (ptr->descriptions [num],description);
    368 	}
    369 
    370 	ptr->callback [num]=callback;
    371 }
    372 
    373 static unsigned int div_ceil(unsigned int a, unsigned int b)
    374 {
    375 	if (!a)
    376 		return 0;
    377 	return ((a - 1) / b) + 1;
    378 }
    379 
    380 int set_file_system_info (void)
    381 
    382 {
    383 	int ext2_detected=0;
    384 	struct ext2_super_block *sb;
    385 
    386 	file_system_info.super_block_offset=1024;
    387 	file_system_info.file_system_size=DefaultTotalBlocks*DefaultBlockSize;
    388 
    389 	low_read ((char *) &file_system_info.super_block,sizeof (struct ext2_super_block),file_system_info.super_block_offset);
    390 
    391 	sb=&file_system_info.super_block;
    392 
    393 	if (sb->s_magic == EXT2_SUPER_MAGIC)
    394 		ext2_detected=1;
    395 
    396 	if (ext2_detected)
    397 		wprintw (command_win,"Detected extended 2 file system on device %s\n",device_name);
    398 	else
    399 		wprintw (command_win,"Warning - Extended 2 filesystem not detected on device %s\n",device_name);
    400 
    401 	if (!ext2_detected && !ForceExt2)
    402 		wprintw (command_win,"You may wish to use the configuration option ForceExt2 on\n");
    403 
    404 	if (ForceExt2 && !ext2_detected)
    405 		wprintw (command_win,"Forcing extended 2 filesystem\n");
    406 
    407 	if (ForceDefault || !ext2_detected)
    408 		wprintw (command_win,"Forcing default parameters\n");
    409 
    410 	refresh_command_win ();
    411 
    412 	if (ext2_detected || ForceExt2) {
    413 		add_ext2_general_commands ();
    414 		if (!set_struct_descriptors (Ext2Descriptors))
    415 			return (0);
    416 	}
    417 
    418 	if (!ForceDefault && ext2_detected) {
    419 
    420 		file_system_info.block_size=EXT2_MIN_BLOCK_SIZE << sb->s_log_block_size;
    421 		if (file_system_info.block_size == EXT2_MIN_BLOCK_SIZE)
    422 			file_system_info.first_group_desc_offset=2*EXT2_MIN_BLOCK_SIZE;
    423 		else
    424 			file_system_info.first_group_desc_offset=file_system_info.block_size;
    425 		file_system_info.groups_count = div_ceil(sb->s_blocks_count,
    426 						 sb->s_blocks_per_group);
    427 
    428 		file_system_info.inodes_per_block=file_system_info.block_size/sizeof (struct ext2_inode);
    429 		file_system_info.blocks_per_group=sb->s_inodes_per_group/file_system_info.inodes_per_block;
    430 		file_system_info.no_blocks_in_group=sb->s_blocks_per_group;
    431 		file_system_info.file_system_size=(sb->s_blocks_count-1)*file_system_info.block_size;
    432 	}
    433 
    434 	else {
    435 		file_system_info.file_system_size=DefaultTotalBlocks*DefaultBlockSize;
    436 		file_system_info.block_size=DefaultBlockSize;
    437 		file_system_info.no_blocks_in_group=DefaultBlocksInGroup;
    438 	}
    439 
    440 	if (file_system_info.file_system_size > 2147483647) {
    441 		wprintw (command_win,"Sorry, filesystems bigger than 2 GB are currently not supported\n");
    442 		return (0);
    443 	}
    444 	return (1);
    445 }
    446 
    447 void init_readline (void)
    448 
    449 {
    450 #ifdef HAVE_READLINE
    451 	rl_completion_entry_function=(Function *) complete_command;
    452 #endif
    453 }
    454 
    455 void init_signals (void)
    456 
    457 {
    458 	signal (SIGWINCH, signal_SIGWINCH_handler);	/* Catch SIGWINCH */
    459 	signal (SIGTERM, signal_SIGTERM_handler);
    460 	signal (SIGSEGV, signal_SIGSEGV_handler);
    461 
    462 }
    463 
    464 void signal_SIGWINCH_handler (int sig_num)
    465 
    466 {
    467 	redraw_request=1;	/* We will handle it in main.c */
    468 
    469 	/* Reset signal handler */
    470 	signal (SIGWINCH, signal_SIGWINCH_handler);
    471 
    472 }
    473 
    474 void signal_SIGTERM_handler (int sig_num)
    475 
    476 {
    477 	prepare_to_close ();
    478 	printf ("Terminated due to signal %d\n",sig_num);
    479 	exit (1);
    480 }
    481 
    482 void signal_SIGSEGV_handler (int sig_num)
    483 
    484 {
    485 	prepare_to_close ();
    486 	printf ("Killed by signal %d!\n",sig_num);
    487 	exit (1);
    488 }
    489 
    490 int process_configuration_file (void)
    491 
    492 {
    493 	char buffer [300];
    494 	char option [80],value [80];
    495 	FILE *fp;
    496 
    497 	strcpy (buffer, ETC_DIR);
    498 	strcat (buffer,"/ext2ed.conf");
    499 
    500 	if ((fp=fopen (buffer,"rt"))==NULL) {
    501 		fprintf (stderr,"Error - Unable to open configuration file %s\n",buffer);
    502 		return (0);
    503 	}
    504 
    505 	while (get_next_option (fp,option,value)) {
    506 		if (strcasecmp (option,"Ext2Descriptors")==0) {
    507 			strcpy (Ext2Descriptors,value);
    508 		}
    509 
    510 		else if (strcasecmp (option,"AlternateDescriptors")==0) {
    511 			strcpy (AlternateDescriptors,value);
    512 		}
    513 
    514 		else if (strcasecmp (option,"LogFile")==0) {
    515 			strcpy (LogFile,value);
    516 		}
    517 
    518 		else if (strcasecmp (option,"LogChanges")==0) {
    519 			if (strcasecmp (value,"on")==0)
    520 				LogChanges = 1;
    521 			else if (strcasecmp (value,"off")==0)
    522 				LogChanges = 0;
    523 			else {
    524 				fprintf (stderr,"Error - Illegal value: %s %s\n",option,value);
    525 				fclose (fp);return (0);
    526 			}
    527 		}
    528 
    529 		else if (strcasecmp (option,"AllowChanges")==0) {
    530 			if (strcasecmp (value,"on")==0)
    531 				AllowChanges = 1;
    532 			else if (strcasecmp (value,"off")==0)
    533 				AllowChanges = 0;
    534 			else {
    535 				fprintf (stderr,"Error - Illegal value: %s %s\n",option,value);
    536 				fclose (fp);return (0);
    537 			}
    538 		}
    539 
    540 		else if (strcasecmp (option,"AllowMountedRead")==0) {
    541 			if (strcasecmp (value,"on")==0)
    542 				AllowMountedRead = 1;
    543 			else if (strcasecmp (value,"off")==0)
    544 				AllowMountedRead = 0;
    545 			else {
    546 				fprintf (stderr,"Error - Illegal value: %s %s\n",option,value);
    547 				fclose (fp);return (0);
    548 			}
    549 		}
    550 
    551 		else if (strcasecmp (option,"ForceExt2")==0) {
    552 			if (strcasecmp (value,"on")==0)
    553 				ForceExt2 = 1;
    554 			else if (strcasecmp (value,"off")==0)
    555 				ForceExt2 = 0;
    556 			else {
    557 				fprintf (stderr,"Error - Illegal value: %s %s\n",option,value);
    558 				fclose (fp);return (0);
    559 			}
    560 		}
    561 
    562 		else if (strcasecmp (option,"DefaultBlockSize")==0) {
    563 			DefaultBlockSize = atoi (value);
    564 		}
    565 
    566 		else if (strcasecmp (option,"DefaultTotalBlocks")==0) {
    567 			DefaultTotalBlocks = strtoul (value,NULL,10);
    568 		}
    569 
    570 		else if (strcasecmp (option,"DefaultBlocksInGroup")==0) {
    571 			DefaultBlocksInGroup = strtoul (value,NULL,10);
    572 		}
    573 
    574 		else if (strcasecmp (option,"ForceDefault")==0) {
    575 			if (strcasecmp (value,"on")==0)
    576 				ForceDefault = 1;
    577 			else if (strcasecmp (value,"off")==0)
    578 				ForceDefault = 0;
    579 			else {
    580 				fprintf (stderr,"Error - Illegal value: %s %s\n",option,value);
    581 				fclose (fp);return (0);
    582 			}
    583 		}
    584 
    585 		else {
    586 			fprintf (stderr,"Error - Unknown option: %s\n",option);
    587 			fclose (fp);return (0);
    588 		}
    589 	}
    590 
    591 	printf ("Configuration completed\n");
    592 	fclose (fp);
    593 	return (1);
    594 }
    595 
    596 int get_next_option (FILE *fp,char *option,char *value)
    597 
    598 {
    599 	char *ptr;
    600 	char buffer [600];
    601 
    602 	if (feof (fp)) return (0);
    603 	do{
    604 		if (feof (fp)) return (0);
    605 		fgets (buffer,500,fp);
    606 	} while (buffer [0]=='#' || buffer [0]=='\n');
    607 
    608 	ptr=parse_word (buffer,option);
    609 	ptr=parse_word (ptr,value);
    610 	return (1);
    611 }
    612 
    613 void check_mounted (char *name)
    614 
    615 {
    616 	FILE *fp;
    617 	char *ptr;
    618 	char current_line [500],current_word [200];
    619 
    620 	mounted=0;
    621 
    622 	if ( (fp=fopen ("/etc/mtab","rt"))==NULL) {
    623 		wprintw (command_win,"Error - Failed to open /etc/mtab. Assuming filesystem is mounted.\n");
    624 		refresh_command_win ();mounted=1;return;
    625 	};
    626 
    627 	while (!feof (fp)) {
    628 		fgets (current_line,500,fp);
    629 		if (feof (fp)) break;
    630 		ptr=parse_word (current_line,current_word);
    631 		if (strcasecmp (current_word,name)==0) {
    632 			mounted=1;fclose (fp);return;
    633 		}
    634 	};
    635 
    636 	fclose (fp);
    637 
    638 	return;
    639 }
    640