2
/* $Id: fileio.c,v 1.3 2000/07/05 15:20:34 jholder Exp $
3
* --------------------------------------------------------------------
4
* see doc/License.txt for License Information
5
* --------------------------------------------------------------------
7
* File name: $Id: fileio.c,v 1.3 2000/07/05 15:20:34 jholder Exp $
11
* Modification history:
13
* Revision 1.3 2000/07/05 15:20:34 jholder
14
* Updated code to remove warnings.
16
* Revision 1.2 2000/05/25 22:28:56 jholder
17
* changes routine names to reflect zmachine opcode names per spec 1.0
19
* Revision 1.1.1.1 2000/05/10 14:21:34 jholder
24
* --------------------------------------------------------------------
30
* File manipulation routines. Should be generic.
35
#include "jzexe.h" /* mol 951115 */
42
static gzFile *gfp = NULL; /* Zcode file pointer */
44
static FILE *gfp = NULL; /* Zcode file pointer */
47
static FILE *sfp = NULL; /* Script file pointer */
48
static FILE *rfp = NULL; /* Record file pointer */
50
#if defined BUFFER_FILES
52
static char gfpbuffer[BUFSIZ];
54
static char sfpbuffer[BUFSIZ];
55
static char rfpbuffer[BUFSIZ];
58
char save_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1] = "story.sav";
59
char script_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1] = "story.scr";
60
char record_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1] = "story.rec";
61
char auxilary_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1] = "story.aux";
63
static int undo_valid = FALSE;
64
static zword_t undo_stack[STACK_SIZE];
66
static int script_file_valid = FALSE;
68
static long story_offset = 0; /* mol 951114 */
69
char *magic = ( char * ) MAGIC_STRING; /* mol */
71
static int save_restore( const char *, int );
76
* This function is called if the game file seems to be a JZEXE file
77
* (standalone game file). If that is the case, story_offset is set
78
* to the beginning of the Z code and the function returns TRUE,
79
* otherwise no action is taken and it returns FALSE.
81
* Magnus Olsson, November 1995
83
int analyze_exefile( void )
87
if ( story_offset > 0 )
89
/* This is wrong; we shouldn't be doing this. */
93
/* Look for the magic string, starting from the beginning. */
97
while ( ( c = jz_getc( gfp ) ) > -1 )
103
i = 1; /* Next character should match magic[1] */
110
else if ( ++i == MAGIC_END )
112
/* Found the magic string! The next byte must be zero. */
113
if ( jz_getc( gfp ) != 0 )
118
/* Read offset and return. We won't concern ourselves with possible
119
* read errors, since their consequences will be detected later on,
120
* when we try to interpret the file as Z code. */
121
story_offset = jz_getc( gfp );
122
story_offset += 256L * jz_getc( gfp );
123
story_offset += 65536L * jz_getc( gfp );
127
/* If we get here, we've reached the end of the infile without success. */
130
} /* analyze_exefile */
136
* Set up the story names intelligently.
137
* John Holder, 28 Sept 1995
139
void set_names( const char *storyname )
143
strcpy( save_name, storyname );
144
strcpy( script_name, storyname );
145
strcpy( record_name, storyname );
146
strcpy( auxilary_name, storyname );
148
/* experimental setting of save_name, added by John Holder 26 July 1995 */
149
per_pos = strrchr( storyname, '.' ); /* find last '.' in storyname. */
150
if ( per_pos ) /* The story file looks like "Odius.dat" or "odieus.z3" */
152
per_pos = strrchr( save_name, '.' );
154
strcat( save_name, ".sav" );
156
per_pos = strrchr( script_name, '.' );
158
strcat( script_name, ".scr" );
160
per_pos = strrchr( record_name, '.' );
162
strcat( record_name, ".rec" );
164
per_pos = strrchr( auxilary_name, '.' );
166
strcat( auxilary_name, ".aux" );
168
else /* The story file looks like: "OdieusQuest" */
170
strcat( save_name, ".sav" );
171
strcat( script_name, ".src" );
172
strcat( record_name, ".rec" );
173
strcat( auxilary_name, ".aux" );
180
* Open game file for read.
184
void open_story( const char *storyname )
187
char tmp[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
191
if ( !STANDALONE_FLAG )
197
/* standalone game; offset to story start is saved in low-endian */
198
/* format after magic string */
200
(unsigned char) magic[MAGIC_END + 1] +
201
(unsigned char) magic[MAGIC_END + 2] * 256L +
202
(unsigned char) magic[MAGIC_END + 3] * 65536L;
205
strcpy( tmp, storyname );
206
if ( ( gfp = jz_open( tmp, "rb" ) ) != NULL )
208
#if defined BUFFER_FILES
210
setbuf( gfp, gfpbuffer );
213
set_names( storyname );
215
#if defined MSDOS || defined OS2
219
sprintf( tmp, "%s.exe", storyname );
220
if ( ( gfp = jz_open( tmp, "rb" ) ) != NULL )
222
#if defined BUFFER_FILES
224
setbuf( gfp, gfpbuffer );
227
set_names( storyname );
233
if ( !STANDALONE_FLAG && ( path = getenv( "INFOCOM_PATH" ) ) == NULL )
235
fprintf( stderr, "%s ", tmp );
236
fatal( "open_story(): Zcode file not found" );
238
else if ( STANDALONE_FLAG && ( path = getenv( "PATH" ) ) == NULL )
240
fprintf( stderr, "%s ", tmp );
241
fatal( "open_story(): Zcode file not found" );
244
/* dos path will be like: */
245
/* SET INFOCOM_PATH = C:\INFOCOM\LTOI1;C:\INFOCOM\LTOI2;C:\INFOCOM\INFORM */
246
#if defined MSDOS || defined OS2
247
p = strtok( path, ";" );
249
/* UNIX path will be like: */
250
/* setenv INFOCOM_PATH /usr/local/lib/ltoi1:/usr/local/lib/ltoi2 */
251
p = strtok( path, ":" );
256
sprintf( tmp, "%s/%s", p, storyname );
257
if ( ( gfp = jz_open( tmp, "rb" ) ) != NULL )
259
#if defined BUFFER_FILES
261
setbuf( gfp, gfpbuffer );
264
set_names( storyname );
266
#if defined MSDOS || defined OS2
270
sprintf( tmp, "%s/%s.exe", p, storyname );
271
if ( ( gfp = jz_open( tmp, "rb" ) ) != NULL )
273
#if defined BUFFER_FILES
275
setbuf( gfp, gfpbuffer );
278
set_names( storyname );
283
#if defined MSDOS || defined OS2
284
p = strtok( NULL, ";" );
286
p = strtok( NULL, ":" );
290
fprintf( stderr, "%s ", tmp );
291
fatal( "open_story(): Zcode file not found" );
298
* Close game file if open.
302
void close_story( void )
315
* Calculate the size of the game file. Only used for very old games that do not
316
* have the game file size in the header.
320
unsigned int get_story_size( void )
322
unsigned long file_length;
324
/* Read whole file to calculate file size */
326
for ( file_length = 0; jz_getc( gfp ) != EOF; file_length++ )
330
/* Calculate length of file in game allocation units */
332
( file_length + ( unsigned long ) ( story_scaler - 1 ) ) / ( unsigned long ) story_scaler;
334
return ( ( unsigned int ) file_length );
336
} /* get_story_size */
341
* Read one game file page.
345
void read_page( int page, void *buffer )
347
unsigned long file_size;
348
unsigned int pages, offset;
350
/* Seek to start of page */
351
jz_seek( gfp, story_offset + ( long ) page * PAGE_SIZE, SEEK_SET );
356
if ( gzread( gfp, buffer, PAGE_SIZE ) == -1 )
358
if ( fread( buffer, PAGE_SIZE, 1, gfp ) != 1 )
361
/* Read failed. Are we in the last page? */
362
file_size = ( unsigned long ) h_file_size *story_scaler;
364
pages = ( unsigned int ) ( ( unsigned long ) file_size / PAGE_SIZE );
365
offset = ( unsigned int ) ( ( unsigned long ) file_size & PAGE_MASK );
367
if ( ( unsigned int ) page == pages )
369
/* Read partial page if this is the last page in the game file */
370
jz_seek( gfp, story_offset + ( long ) page * PAGE_SIZE, SEEK_SET );
372
if ( gzread( gfp, buffer, offset ) == -1 )
374
if ( fread( buffer, offset, 1, gfp ) != 1 )
377
fatal( "read_page(): Zcode file read error" );
387
* Verify game ($verify verb). Add all bytes in game file except for bytes in
388
* the game file header.
392
void z_verify( void )
394
unsigned long file_size;
395
unsigned int pages, offset;
396
unsigned int start, end, i, j;
397
zword_t checksum = 0;
398
zbyte_t buffer[PAGE_SIZE] = { 0 };
399
char szBuffer[6] = { 0 };
401
/* Print version banner */
404
write_string( "Running on " );
405
write_string( JZIPVER );
406
write_string( " (" );
410
write_string( "Generic" );
413
write_string( "Amiga" );
415
case INTERP_ATARI_ST:
416
write_string( "Atari ST" );
419
write_string( "DOS" );
422
write_string( "UNIX" );
425
write_string( "VMS" );
428
write_string( "). Reporting Spec " );
429
sprintf( szBuffer, "%d.%d", get_byte( H_STANDARD_HIGH ), get_byte( H_STANDARD_LOW ) );
430
write_string( szBuffer );
431
write_string( " Compliance." );
434
write_string( "Compile options: " );
436
write_string( "USE_QUETZAL " );
439
write_string( "STRICTZ " );
442
write_string( "USE_ZLIB " );
445
write_string( "LOUSY_RANDOM " );
448
write_string( "HARD_COLORS " );
452
write_string( "Release " );
453
write_string( JZIPRELDATE );
457
write_string( "Playing a Version " );
458
z_print_num( (zword_t) GLOBALVER );
459
write_string( " Story." );
464
/* Calculate game file dimensions */
466
file_size = ( unsigned long ) h_file_size *story_scaler;
468
pages = ( unsigned int ) ( ( unsigned long ) file_size / PAGE_SIZE );
469
offset = ( unsigned int ) file_size & PAGE_MASK;
471
/* Sum all bytes in game file, except header bytes */
473
for ( i = 0; i <= pages; i++ )
475
read_page( i, buffer );
476
start = ( i == 0 ) ? 64 : 0;
477
end = ( i == pages ) ? offset : PAGE_SIZE;
478
for ( j = start; j < end; j++ )
480
checksum += buffer[j];
484
/* Make a conditional jump based on whether the checksum is equal */
486
conditional_jump( checksum == h_checksum );
494
* Read a default file name from the memory of the Z-machine and
495
* copy it to an array.
499
static void get_default_name( char *default_name, zword_t addr )
507
len = get_byte( addr );
509
for ( i = 0; i < len; i++ )
512
c = get_byte( addr );
517
if ( strchr( default_name, '.' ) == 0 )
519
strcpy( default_name + i, ".aux" );
525
strcpy( default_name, auxilary_name );
528
} /* get_default_name */
534
* Saves data to disk. Returns:
540
int z_save( int argc, zword_t table, zword_t bytes, zword_t name )
542
char new_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
543
char default_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
546
#if defined BUFFER_FILES
547
char afpbuffer[BUFSIZ];
553
get_default_name( default_name, name );
554
if ( get_file_name( new_name, default_name, GAME_SAVE_AUX ) != 0 )
559
if ( ( afp = fopen( new_name, "wb" ) ) == NULL )
564
#if defined BUFFER_FILES
565
setbuf( afp, afpbuffer );
568
status = fwrite( datap + table, bytes, 1, afp );
574
strcpy( auxilary_name, default_name );
581
/* Get the file name */
584
if ( get_file_name( new_name, save_name, GAME_SAVE ) == 0 )
586
/* Do a save operation */
587
if ( save_restore( new_name, GAME_SAVE ) == 0 )
590
file_cleanup( new_name, GAME_SAVE );
592
/* Save the new name as the default file name */
593
strcpy( save_name, new_name );
595
/* Indicate success */
603
/* Return result of save to Z-code */
607
conditional_jump( status == 0 );
611
store_operand( (zword_t)(( status == 0 ) ? 1 : 0) );
621
* Restore game state from disk. Returns:
623
* 2 = restore succeeded
626
int z_restore( int argc, zword_t table, zword_t bytes, zword_t name )
628
char new_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
629
char default_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
632
#if defined BUFFER_FILES
633
char afpbuffer[BUFSIZ];
641
get_default_name( default_name, name );
642
if ( get_file_name( new_name, default_name, GAME_LOAD_AUX ) == 0 )
647
if ( ( afp = fopen( new_name, "rb" ) ) == NULL )
652
#if defined BUFFER_FILES
653
setbuf( afp, afpbuffer );
656
status = fread( datap + table, bytes, 1, afp );
662
strcpy( auxilary_name, default_name );
669
/* Get the file name */
671
if ( get_file_name( new_name, save_name, GAME_RESTORE ) == 0 )
673
/* Do the restore operation */
674
if ( save_restore( new_name, GAME_RESTORE ) == 0 )
676
/* Reset the status region (this is just for Seastalker) */
680
blank_status_line( );
684
file_cleanup( new_name, GAME_SAVE );
686
/* Save the new name as the default file name */
687
strcpy( save_name, new_name );
689
/* Indicate success */
696
/* Return result of save to Z-code */
700
conditional_jump( status == 0 );
704
store_operand( (zword_t)(( status == 0 ) ? 2 : 0) );
713
* Save the current Z machine state in memory for a future undo. Returns:
714
* -1 = feature unavailable
720
void z_save_undo( void )
722
/* Check if undo is available first */
723
if ( undo_datap != NULL )
725
/* Save the undo data and return success */
726
save_restore( NULL, UNDO_SAVE );
732
/* If no memory for data area then say undo is not available */
733
store_operand( ( zword_t ) - 1 );
741
* Restore the current Z machine state from memory. Returns:
742
* -1 = feature unavailable
744
* 2 = restore succeeded
748
void z_restore_undo( void )
750
/* Check if undo is available first */
751
if ( undo_datap != NULL )
753
/* If no undo save done then return an error */
754
if ( undo_valid == TRUE )
756
/* Restore the undo data and return success */
757
save_restore( NULL, UNDO_RESTORE );
767
/* If no memory for data area then say undo is not available */
768
store_operand( ( zword_t ) - 1 );
771
} /* z_restore_undo */
777
* Swap the low and high bytes in every word of the specified array.
778
* The length is specified in BYTES!
780
* This routine added by Mark Phillips(msp@bnr.co.uk), Thanks Mark!
782
#if !defined(USE_QUETZAL)
783
void swap_bytes( zword_t * ptr, int len )
785
unsigned char *pbyte;
788
len /= 2; /* convert len into number of 2 byte words */
790
pbyte = ( unsigned char * ) ptr;
807
* Common save and restore code. Just save or restore the game stack and the
808
* writeable data area.
812
static int save_restore( const char *file_name, int flag )
816
#if defined BUFFER_FILES
817
char tfpbuffer[BUFSIZ];
819
int scripting_flag = 0, status = 0;
821
#if !defined(USE_QUETZAL)
823
int little_endian = 0;
825
/* Find out if we are big-endian */
827
if ( *( zbyte_t * ) & zw )
828
{ /* We are little-endian, like an Intel 80x86 chip. */
833
/* Open the save file and disable scripting */
835
if ( flag == GAME_SAVE || flag == GAME_RESTORE )
837
if ( ( tfp = fopen( file_name, ( flag == GAME_SAVE ) ? "wb" : "rb" ) ) == NULL )
839
output_line( "Cannot open SAVE file" );
842
#if defined BUFFER_FILES
843
setbuf( tfp, tfpbuffer );
845
scripting_flag = get_word( H_FLAGS ) & SCRIPTING_FLAG;
846
set_word( H_FLAGS, get_word( H_FLAGS ) & ( ~SCRIPTING_FLAG ) );
849
#if defined(USE_QUETZAL)
850
if ( flag == GAME_SAVE )
852
status = !save_quetzal( tfp, gfp );
854
else if ( flag == GAME_RESTORE )
856
status = !restore_quetzal( tfp, gfp );
860
#endif /* defined(USE_QUETZAL) */
861
/* Push PC, FP, version and store SP in special location */
863
stack[--sp] = ( zword_t ) ( pc / PAGE_SIZE );
864
stack[--sp] = ( zword_t ) ( pc % PAGE_SIZE );
866
stack[--sp] = h_version;
869
/* Save or restore stack */
871
#if !defined(USE_QUETZAL)
872
if ( flag == GAME_SAVE )
875
swap_bytes( stack, sizeof ( stack ) );
876
if ( status == 0 && fwrite( stack, sizeof ( stack ), 1, tfp ) != 1 )
879
swap_bytes( stack, sizeof ( stack ) );
881
else if ( flag == GAME_RESTORE )
884
swap_bytes( stack, sizeof ( stack ) );
885
if ( status == 0 && fread( stack, sizeof ( stack ), 1, tfp ) != 1 )
888
swap_bytes( stack, sizeof ( stack ) );
891
#endif /* !defined(USE_QUETZAL) */
893
if ( flag == UNDO_SAVE )
895
memmove( undo_stack, stack, sizeof ( stack ) );
897
else /* if (flag == UNDO_RESTORE) */
899
memmove( stack, undo_stack, sizeof ( stack ) );
903
/* Restore SP, check version, restore FP and PC */
907
if ( stack[sp++] != h_version )
909
fatal( "save_restore(): Wrong game or version" );
914
pc += ( unsigned long ) stack[sp++] * PAGE_SIZE;
916
/* Save or restore writeable game data area */
918
#if !defined(USE_QUETZAL)
919
if ( flag == GAME_SAVE )
921
if ( status == 0 && fwrite( datap, h_restart_size, 1, tfp ) != 1 )
924
else if ( flag == GAME_RESTORE )
926
if ( status == 0 && fread( datap, h_restart_size, 1, tfp ) != 1 )
930
#endif /* !defined(USE_QUETZAL) */
932
if ( flag == UNDO_SAVE )
934
memmove( undo_datap, datap, h_restart_size );
936
else /* if (flag == UNDO_RESTORE) */
938
memmove( datap, undo_datap, h_restart_size );
942
#if defined(USE_QUETZAL)
944
#endif /* defined(USE_QUETZAL) */
947
/* Close the save file and restore scripting */
949
if ( flag == GAME_SAVE )
952
if ( scripting_flag )
954
set_word( H_FLAGS, get_word( H_FLAGS ) | SCRIPTING_FLAG );
957
else if ( flag == GAME_RESTORE )
961
restart_interp( scripting_flag );
964
/* Handle read or write errors */
968
if ( flag == GAME_SAVE )
970
output_line( "Write to SAVE file failed" );
975
fatal( "save_restore(): Read from SAVE file failed" );
986
* Open the scripting file.
990
void open_script( void )
992
char new_script_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
994
/* Open scripting file if closed */
995
if ( scripting == OFF )
997
if ( script_file_valid == TRUE )
999
sfp = fopen( script_name, "a" );
1001
/* Turn on scripting if open succeeded */
1004
#if defined BUFFER_FILES
1005
setbuf( sfp, sfpbuffer );
1011
output_line( "Script file open failed" );
1015
{ /* Get scripting file name and record it */
1016
if ( get_file_name( new_script_name, script_name, GAME_SCRIPT ) == 0 )
1018
/* Open scripting file */
1019
sfp = fopen( new_script_name, "w" );
1021
/* Turn on scripting if open succeeded */
1024
#if defined BUFFER_FILES
1025
setbuf( sfp, sfpbuffer );
1027
script_file_valid = TRUE;
1029
/* Make file name the default name */
1030
strcpy( script_name, new_script_name );
1032
/* Turn on scripting */
1037
output_line( "Script file create failed" );
1043
/* Set the scripting flag in the game file flags */
1044
if ( scripting == ON )
1046
set_word( H_FLAGS, get_word( H_FLAGS ) | SCRIPTING_FLAG );
1050
set_word( H_FLAGS, get_word( H_FLAGS ) & ( ~SCRIPTING_FLAG ) );
1057
* Flush the scripting file.
1060
void flush_script( void )
1062
/* Flush scripting file if open */
1063
if ( scripting == ON )
1073
* Close the scripting file.
1076
void close_script( void )
1078
/* Close scripting file if open */
1079
if ( scripting == ON )
1084
file_cleanup( script_name, GAME_SCRIPT );
1086
/* Turn off scripting */
1090
/* Set the scripting flag in the game file flags */
1091
if ( scripting == OFF )
1093
set_word( H_FLAGS, get_word( H_FLAGS ) & ( ~SCRIPTING_FLAG ) );
1097
set_word( H_FLAGS, get_word( H_FLAGS ) | SCRIPTING_FLAG );
1100
} /* close_script */
1105
* Write one character to scripting file.
1107
* Check the state of the scripting flag first. Older games only set the
1108
* scripting flag in the game flags instead of calling the set_print_modes
1109
* function. This is because they expect a physically attached printer that
1110
* doesn't need opening like a file.
1113
void script_char( int c )
1116
/* Check the state of the scripting flag in the game flags. If it is on
1117
* then check to see if the scripting file is open as well */
1119
if ( ( get_word( H_FLAGS ) & SCRIPTING_FLAG ) != 0 && scripting == OFF )
1124
/* Check the state of the scripting flag in the game flags. If it is off
1125
* then check to see if the scripting file is closed as well */
1127
if ( ( get_word( H_FLAGS ) & SCRIPTING_FLAG ) == 0 && scripting == ON )
1132
/* If scripting file is open, we are in the text window and the character is
1133
* printable then write the character */
1135
if ( scripting == ON && scripting_disable == OFF && ( c == '\n' || ( isprint( c ) ) ) )
1145
* Write a string to the scripting file.
1149
void script_string( const char *s )
1154
script_char( *s++ );
1157
} /* script_string */
1162
* Write a string followed by a new line to the scripting file.
1166
void script_line( const char *s )
1172
/* Write new line */
1180
* Write a new line to the scripting file.
1184
void script_new_line( void )
1187
script_char( '\n' );
1189
} /* script_new_line */
1194
* Turn on recording of all input to an output file.
1198
void open_record( void )
1200
char new_record_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
1202
/* If recording or playback is already on then complain */
1204
if ( recording == ON || replaying == ON )
1206
output_line( "Recording or playback are already active." );
1209
{ /* Get recording file name */
1210
if ( get_file_name( new_record_name, record_name, GAME_RECORD ) == 0 )
1212
/* Open recording file */
1213
rfp = fopen( new_record_name, "w" );
1215
/* Turn on recording if open succeeded */
1218
#if defined BUFFER_FILES
1219
setbuf( rfp, rfpbuffer );
1221
/* Make file name the default name */
1222
strcpy( record_name, new_record_name );
1224
/* Set recording on */
1229
output_line( "Record file create failed" );
1239
* Write a string followed by a new line to the recording file.
1243
void record_line( const char *s )
1245
if ( recording == ON && replaying == OFF )
1248
fprintf( rfp, "%s\n", s );
1256
* Write a key followed by a new line to the recording file.
1260
void record_key( int c )
1262
if ( recording == ON && replaying == OFF )
1265
fprintf( rfp, "<%0o>\n", c );
1273
* Turn off recording of all input to an output file.
1277
void close_record( void )
1279
/* Close recording file */
1287
if ( recording == ON )
1289
file_cleanup( record_name, GAME_RECORD );
1291
else /* (replaying == ON) */
1293
file_cleanup( record_name, GAME_PLAYBACK );
1297
/* Set recording and replaying off */
1302
} /* close_record */
1307
* Take input from command file instead of keyboard.
1311
void z_input_stream( int arg )
1313
char new_record_name[Z_FILENAME_MAX + Z_PATHNAME_MAX + 1];
1317
/* If recording or replaying is already on then complain */
1319
if ( recording == ON || replaying == ON )
1321
output_line( "Recording or replaying is already active." );
1324
{ /* Get recording file name */
1326
if ( get_file_name( new_record_name, record_name, GAME_PLAYBACK ) == 0 )
1328
/* Open recording file */
1329
rfp = fopen( new_record_name, "r" );
1331
/* Turn on recording if open succeeded */
1334
#if defined BUFFER_FILES
1335
setbuf( rfp, rfpbuffer );
1337
/* Make file name the default name */
1338
strcpy( record_name, new_record_name );
1340
/* Set replaying on */
1345
output_line( "Record file open failed" );
1350
} /* z_input_stream */
1355
* Get a line of input from the command file.
1359
int playback_line( int buflen, char *buffer, int *read_size )
1363
if ( recording == ON || replaying == OFF )
1368
if ( fgets( buffer, buflen, rfp ) == NULL )
1375
cp = strrchr( buffer, '\n' );
1380
*read_size = strlen( buffer );
1381
output_line( buffer );
1386
} /* playback_line */
1391
* Get a key from the command file.
1395
int playback_key( void )
1399
if ( recording == ON || replaying == OFF )
1404
if ( fscanf( rfp, "<%o>\n", &c ) == EOF )
1412
} /* playback_key */