blob: 4a29979bdfa69e9aa6d0abe0c7ace6771395311c [file] [log] [blame]
Theodore Ts'o583a1ce2002-05-11 13:00:22 -04001/*
2
3/usr/src/ext2ed/main.c
4
5A part of the extended file system 2 disk editor.
6
7------------
8Main program
9------------
10
11This file mostly contains:
12
131. A list of global variables used through the entire program.
142. The parser, which asks the command line from the user.
153. The dispatcher, which analyzes the command line and calls the appropriate handler function.
164. A command pattern matcher which is used along with the readline completion feature.
175. A function which tells the user that an internal error has occured.
18
19First written on: March 30 1995
20
21Copyright (C) 1995 Gadi Oxman
22
23*/
Theodore Ts'o5e941d22002-05-13 07:53:11 -040024
Theodore Ts'od1154eb2011-09-18 17:34:37 -040025#include "config.h"
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040026#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
Theodore Ts'o5e941d22002-05-13 07:53:11 -040029#include <signal.h>
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040030
Theodore Ts'o5e941d22002-05-13 07:53:11 -040031#ifdef HAVE_READLINE
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040032#include <readline.h>
33#include <history.h>
Theodore Ts'o5e941d22002-05-13 07:53:11 -040034#endif
35
36#ifdef HAVE_GETOPT_H
37#include <getopt.h>
38#else
39extern int optind;
40extern char *optarg;
41#endif
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040042
43#include "ext2ed.h"
44
45/* Global variables */
46
47/*
48
49Configuration file options
50
51The following variables will be set by init.c to the values selected in the user configuration file.
52They are initialized below to some logical defaults.
53
54*/
55
56
57char Ext2Descriptors [200]="ext2.descriptors"; /* The location of the ext2 filesystem object definition */
58char AlternateDescriptors [200]=""; /* We allow the user to define additional structures */
59char LogFile [200]="ext2ed.log"; /* The location of the log file - Each write will be logged there */
60int LogChanges=1; /* 1 enables logging, 0 diables logging */
61int AllowChanges=0; /* When set, the enablewrite command will fail */
62int AllowMountedRead=0; /* Behavior when trying to open a mounted filesystem read-only */
63int ForceExt2=0; /* When set, ext2 autodetection is overridden */
64int DefaultBlockSize=1024;
65unsigned long DefaultTotalBlocks=2097151;
66unsigned long DefaultBlocksInGroup=8192; /* The default values are used when an ext2 filesystem is not */
67int ForceDefault=0; /* detected, or ForceDefault is set */
68
69char last_command_line [80]; /* A simple one command cache, in addition to the readline history */
70
71char device_name [80]; /* The location of the filesystem */
72FILE *device_handle=NULL; /* This is passed to the fopen / fread ... commands */
73long device_offset; /* The current position in the filesystem */
74 /* Note that we have a 2 GB limitation */
Theodore Ts'oefc6f622008-08-27 23:07:54 -040075
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040076int mounted=0; /* This is set when we find that the filesystem is mounted */
77
78struct struct_commands general_commands,ext2_commands; /* Used to define the general and ext2 commands */
79struct struct_descriptor *first_type,*last_type,*current_type; /* Used to access the double linked list */
80struct struct_type_data type_data; /* The current data is sometimes stored here */
81struct struct_file_system_info file_system_info; /* Essential information on the filesystem */
82struct struct_file_info file_info,first_file_info; /* Used by file_com.c to access files */
83struct struct_group_info group_info; /* Used by group_com.c */
84struct struct_super_info super_info; /* Used by super_com.c */
85struct struct_remember_lifo remember_lifo; /* A circular memory of objects */
86struct struct_block_bitmap_info block_bitmap_info; /* Used by blockbitmap_com.c */
87struct struct_inode_bitmap_info inode_bitmap_info; /* Used by inodebitmap_com.c */
88
89int redraw_request=0; /* Is set by a signal handler to handle terminal */
90 /* screen size change. */
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040091
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040092
Theodore Ts'o5e941d22002-05-13 07:53:11 -040093/*
94 * We just call the parser to get commands from the user. We quit when
95 * parser returns.
96 */
97int main (int argc, char **argv)
Theodore Ts'o583a1ce2002-05-11 13:00:22 -040098{
Theodore Ts'o5e941d22002-05-13 07:53:11 -040099 int write_priv = 0;
100 int c;
101 char *buf;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400102
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400103 if (!init ())
104 return (1);
105 while ((c = getopt (argc, argv, "w")) != EOF) {
106 switch (c) {
107 case 'w':
108 write_priv++;
109 break;
110 }
111 }
112 if (optind < argc) {
113 buf = malloc(strlen(argv[optind]) + 32);
114 if (!buf) {
115 fprintf(stderr, "Couldn't allocate filename buffer\n");
116 exit(1);
117 }
118 strcpy(buf, "set_device ");
119 strcat(buf, argv[optind]);
120 set_device(buf);
121 free(buf);
122 if (write_priv) {
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400123 wprintw (command_win,"\n");
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400124 enable_write("enable_write");
125 }
126 }
127 parser (); /* Get and parse user commands */
128 prepare_to_close(); /* Do some cleanup */
129 printf("Quitting ...\n");
130 return(0);
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400131}
132
133
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400134/*
135 * Read a character from the command window
136 */
137int command_read_key()
138{
139 int key = 0;
140
141 while (!key) {
142 if (redraw_request) {
143 redraw_all();
144 redraw_request=0;
145 }
146 key = wgetch(command_win);
147 switch (key) {
148 case 0x1A:
149 key = 0;
150 kill(getpid(), SIGTSTP);
151 break;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400152
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400153 case KEY_NPAGE:
154 pgdn("");
155 refresh_command_win ();
156 break;
157
158 case KEY_PPAGE:
159 pgup("");
160 refresh_command_win ();
161 break;
162 case ERR:
163 key = 0;
164 break;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400165
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400166 case KEY_BACKSPACE:
167 key = '\b';
168 }
169 if ((key < 32 && key != '\b' && key != '\n') ||
170 (key > 127))
171 key = 0;
172 }
173 return key;
174}
175
176#ifdef HAVE_READLINE
177int rl_getc_replacement(FILE *f)
178{
179 int key = command_read_key();
180
181 if (key == '\b') {
182 if (rl_point > 0)
183 wprintw(command_win, "\b \b");
184 } else
185 wprintw(command_win, "%c", key);
186 return key;
187}
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400188
189/*
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400190 * This function asks the user for a command and calls the dispatcher
191 * function, dispatch, to analyze it. We use the readline library
192 * function readline to read the command, hence all the usual readline
193 * keys are available. The new command is saved both in the
194 * readline's history and in our tiny one-command cache, so that only
195 * the enter key is needed to retype it.
196 */
197void parser (void)
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400198{
199 char *ptr,command_line [80];
200 int quit=0;
201
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400202#if 0
203 noecho();
204 cbreak();
205 keypad(command_win, 1);
206 wtimeout(command_win, 100);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400207
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400208 rl_getc_function = rl_getc_replacement;
209#endif
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400210
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400211 while (!quit) {
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400212 /* Terminal screen size has changed */
213 if (redraw_request) {
214 redraw_all();
215 redraw_request=0;
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400216 }
217
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400218 wmove (command_win,0,0);
219 wclrtoeol (command_win);
220 wprintw (command_win,"ext2ed > ");
221 refresh_command_win ();
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400222
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400223 /*
224 * The ncurses library optimizes cursor movement by
225 * keeping track of the cursor position. However, by
226 * using the readline library I'm breaking its
227 * assumptions. The double -1 arguments tell ncurses
228 * to disable cursor movement optimization this
229 * time.
230 */
231 mvcur (-1,-1,LINES-COMMAND_WIN_LINES,0);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400232
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400233 /* echo (); */
234 ptr=readline ("ext2ed > ");
235 /* noecho (); */
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400236
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400237 /*
238 * Readline allocated the buffer - Copy the string
239 * and free the allocated buffer
240 * XXX WHY???
241 */
242 strcpy (command_line,ptr);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400243 free (ptr);
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400244
245 if (*command_line != 0)
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400246 add_history (command_line);
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400247
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400248 /* If only enter was pressed, recall the last command */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400249 if (*command_line==0)
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400250 strcpy (command_line,last_command_line);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400251
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400252 /* Emulate readline's actions for ncurses */
253 mvcur (-1,-1,LINES-COMMAND_WIN_LINES,0);
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400254 werase (command_win);
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400255 wprintw (command_win,"ext2ed > ");
256 wprintw (command_win,command_line);
257 wprintw (command_win,"\n");
258 refresh_command_win ();
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400259
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400260 /* Save this command in our tiny cache */
261 strcpy (last_command_line,command_line);
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400262
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400263 /* And call dispatch to do the actual job */
264 quit=dispatch (command_line);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400265 }
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400266}
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400267#else
268void read_line(char * foo) {
269 char * chptr = foo;
270 int ch;
271 int done = 0;
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400272
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400273 while (!done && (ch = command_read_key())) {
274 switch (ch) {
275 case '\n':
276 done = 1;
277 break;
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400278
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400279 case '\b':
280 if (chptr > foo) {
281 wprintw(command_win, "\b \b");
282 chptr--;
283 }
284 break;
285
286 default:
287 if (ch > 256)
288 break;
289 if (ch == '\n') break;
290 *chptr++ = ch;
291 wprintw(command_win, "%c", ch);
292 break;
293 }
294 }
295 *chptr = '\0';
296}
297
298void parser (void)
299{
300 char command_line [80];
301 int quit=0;
302
303 noecho();
304 cbreak();
305 wtimeout(command_win, 100);
306 keypad(command_win, 1);
307
308 while (!quit) {
309 /* Terminal screen size has changed */
310 if (redraw_request) {
311 redraw_all();
312 redraw_request=0;
313 }
314
315 wmove (command_win,0,0);wclrtoeol (command_win);
316
317 wmove(command_win, 0, 0);
318 wprintw(command_win, "ext2ed > ");
319 read_line(command_line);
320
321 /* If only enter was pressed, recall the last command */
322 if (*command_line==0)
323 strcpy (command_line,last_command_line);
324
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400325 mvcur (-1,-1,LINES-COMMAND_WIN_LINES + 1,0);
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400326
327 strcpy (last_command_line,command_line); /* Save this command in our tiny cache */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400328
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400329 /* And call dispatch to do the actual job */
330 quit=dispatch (command_line);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400331 }
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400332}
333#endif
334
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400335
336/*
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400337 * This is a very important function. Its task is to recieve a command
338 * name and link it to a C function. There are three types of commands:
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400339 *
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400340 * 1. General commands - Always available and accessed through
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400341 * general_commands.
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400342 * 2. Ext2 specific commands - Available when editing an ext2
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400343 * filesystem, accessed through ext2_commands.
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400344 * 3. Type specific commands - Those are changing according to the
345 * current type. The global variable current_type points to the
346 * current object definition (of type struct_descriptor). In it, the
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400347 * struct_commands entry contains the type specific commands links.
348 *
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400349 * Overriding is an important feature - Much like in C++ : The same
350 * command name can dispatch to different functions. The overriding
351 * priority is 3,2,1; That is - A type specific command will always
352 * override a general command. This is used through the program to
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400353 * allow fine tuned operation.
354 *
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400355 * When an handling function is found, it is called along with the
356 * command line that was passed to us. The handling function is then
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400357 * free to interpert the arguments in its own style.
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400358 */
359int dispatch (char *command_line)
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400360{
361 int i,found=0;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400362
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400363 char command [80];
364
365 parse_word (command_line,command);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400366
367 if (strcasecmp (command,"quit")==0) return (1);
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400368
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400369 /* 1. Search for type specific commands FIRST - Allows
370 overriding of a general command */
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400371
372 if (current_type != NULL)
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400373 for (i=0;
374 i<=current_type->type_commands.last_command && !found;
375 i++) {
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400376 if (strcasecmp (command,current_type->type_commands.names [i])==0) {
377 (*current_type->type_commands.callback [i]) (command_line);
378 found=1;
379 }
380 }
381
382 /* 2. Now search for ext2 filesystem general commands */
383
384 if (!found)
385 for (i=0;i<=ext2_commands.last_command && !found;i++) {
386 if (strcasecmp (command,ext2_commands.names [i])==0) {
387 (*ext2_commands.callback [i]) (command_line);
388 found=1;
389 }
390 }
391
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400392
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400393 /* 3. If not found, search the general commands */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400394
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400395 if (!found)
396 for (i=0;i<=general_commands.last_command && !found;i++) {
397 if (strcasecmp (command,general_commands.names [i])==0) {
398 (*general_commands.callback [i]) (command_line);
399 found=1;
400 }
401 }
402
403 /* 4. If not found, issue an error message and return */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400404
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400405 if (!found) {
406 wprintw (command_win,"Error: Unknown command\n");
407 refresh_command_win ();
408 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400409
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400410 return (0);
411}
412
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400413
414/*
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400415 *
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400416 * This function copies the next word in source to the variable dest,
417 * ignoring whitespaces. It returns a pointer to the next word in
418 * source. It is used to split the command line into command and arguments.
419 */
420char *parse_word (char *source,char *dest)
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400421{
422 char ch,*source_ptr,*target_ptr;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400423
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400424 if (*source==0) {
425 *dest=0;
426 return (source);
427 };
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400428
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400429 source_ptr=source;target_ptr=dest;
430 do {
431 ch=*source_ptr++;
432 } while (! (ch>' ' && ch<='z') && ch!=0);
433
434 while (ch>' ' && ch<='z') {
435 *target_ptr++=ch;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400436 ch=*source_ptr++;
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400437 }
438
439 *target_ptr=0;
440
441 source_ptr--;
442 do {
443 ch=*source_ptr++;
444 } while (! (ch>' ' && ch<='z') && ch!=0);
445
446 return (--source_ptr);
447}
448
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400449/*
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400450 * text is the partial command entered by the user; We assume that it
451 * is a part of a command - I didn't write code for smarter completion.
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400452 *
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400453 * The state variable is an index which tells us how many possible
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400454 * completions we already returned to readline.
455 *
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400456 * We return only one possible completion or (char *) NULL if there
457 * are no more completions. This function will be called by readline
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400458 * over and over until we tell it to stop.
459 *
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400460 * While scanning for possible completions, we use the same priority
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400461 * definition which was used in dispatch.
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400462 */
463#if HAVE_READLINE
464char *complete_command (char *text,int state)
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400465{
466 int state_index=-1;
467 int i,len;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400468
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400469 len=strlen (text);
470
471 /* Is the command type specific ? */
472
473 if (current_type != NULL)
474 for (i=0;i<=current_type->type_commands.last_command;i++) {
475 if (strncmp (current_type->type_commands.names [i],text,len)==0) {
476 state_index++;
477 if (state==state_index) {
478 return (dupstr (current_type->type_commands.names [i]));
479 }
480 }
481 }
482
483 /* No, pehaps ext2 specific command then ? */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400484
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400485 for (i=0;i<=ext2_commands.last_command;i++) {
486 if (strncmp (ext2_commands.names [i],text,len)==0) {
487 state_index++;
488 if (state==state_index)
489 return (dupstr (ext2_commands.names [i]));
490 }
491 }
492
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400493
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400494 /* Check for a general command */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400495
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400496 for (i=0;i<=general_commands.last_command;i++) {
497 if (strncmp (general_commands.names [i],text,len)==0) {
498 state_index++;
499 if (state==state_index)
500 return (dupstr (general_commands.names [i]));
501 }
502 }
503
504 /* quit is handled differently */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400505
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400506 if (strncmp ("quit",text,len)==0) {
507 state_index++;
508 if (state==state_index)
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400509 return (dupstr ("quit"));
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400510 }
511
512 /* No more completions */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400513
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400514 return ((char *) NULL);
515}
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400516#endif
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400517
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400518
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400519/*
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400520 * Nothing special - Just allocates enough space and copy the string.
521 */
522char *dupstr (char *src)
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400523{
524 char *ptr;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400525
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400526 ptr=(char *) malloc (strlen (src)+1);
527 strcpy (ptr,src);
528 return (ptr);
529}
530
531#ifdef DEBUG
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400532/*
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400533 * This function reports an internal error. It is almost not used. One
534 * place in which I do check for internal errors is disk.c.
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400535 *
Theodore Ts'o5e941d22002-05-13 07:53:11 -0400536 * We just report the error, and try to continue ...
537 */
538void internal_error (char *description,char *source_name,char *function_name)
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400539{
540 wprintw (command_win,"Internal error - Found by source: %s.c , function: %s\n",source_name,function_name);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400541 wprintw (command_win,"\t%s\n",description);
Theodore Ts'o583a1ce2002-05-11 13:00:22 -0400542 wprintw (command_win,"Press enter to (hopefully) continue\n");
543 refresh_command_win ();getch ();werase (command_win);
544}
545
Theodore Ts'o0f31c732002-05-11 13:03:25 -0400546#endif