|
Packit |
4e1bf9 |
/* io.c: i/o routines for the ed line editor */
|
|
Packit |
4e1bf9 |
/* GNU ed - The GNU line editor.
|
|
Packit |
4e1bf9 |
Copyright (C) 1993, 1994 Andrew Moore, Talke Studio
|
|
Packit |
4e1bf9 |
Copyright (C) 2006-2017 Antonio Diaz Diaz.
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
This program is free software: you can redistribute it and/or modify
|
|
Packit |
4e1bf9 |
it under the terms of the GNU General Public License as published by
|
|
Packit |
4e1bf9 |
the Free Software Foundation, either version 2 of the License, or
|
|
Packit |
4e1bf9 |
(at your option) any later version.
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
This program is distributed in the hope that it will be useful,
|
|
Packit |
4e1bf9 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
4e1bf9 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
4e1bf9 |
GNU General Public License for more details.
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
You should have received a copy of the GNU General Public License
|
|
Packit |
4e1bf9 |
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
4e1bf9 |
*/
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
#include <errno.h>
|
|
Packit |
4e1bf9 |
#include <stdio.h>
|
|
Packit |
4e1bf9 |
#include <string.h>
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
#include "ed.h"
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
static const line_t * unterminated_line = 0; /* last line has no '\n' */
|
|
Packit |
4e1bf9 |
int linenum_ = 0; /* script line number */
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
void reset_unterminated_line( void ) { unterminated_line = 0; }
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
void unmark_unterminated_line( const line_t * const lp )
|
|
Packit |
4e1bf9 |
{ if( unterminated_line == lp ) unterminated_line = 0; }
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
static bool unterminated_last_line( void )
|
|
Packit |
4e1bf9 |
{ return ( unterminated_line != 0 &&
|
|
Packit |
4e1bf9 |
unterminated_line == search_line_node( last_addr() ) ); }
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
int linenum( void ) { return linenum_; }
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
/* print text to stdout */
|
|
Packit |
4e1bf9 |
static void print_line( const char * p, int len, const int pflags )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
const char escapes[] = "\a\b\f\n\r\t\v\\";
|
|
Packit |
4e1bf9 |
const char escchars[] = "abfnrtv\\";
|
|
Packit |
4e1bf9 |
int col = 0;
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
if( pflags & GNP ) { printf( "%d\t", current_addr() ); col = 8; }
|
|
Packit |
4e1bf9 |
while( --len >= 0 )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
const unsigned char ch = *p++;
|
|
Packit |
4e1bf9 |
if( !( pflags & GLS ) ) putchar( ch );
|
|
Packit |
4e1bf9 |
else
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
if( ++col > window_columns() ) { col = 1; fputs( "\\\n", stdout ); }
|
|
Packit |
4e1bf9 |
if( ch >= 32 && ch <= 126 && ch != '\\' ) putchar( ch );
|
|
Packit |
4e1bf9 |
else
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
char * const p = strchr( escapes, ch );
|
|
Packit |
4e1bf9 |
++col; putchar('\\');
|
|
Packit |
4e1bf9 |
if( ch && p ) putchar( escchars[p-escapes] );
|
|
Packit |
4e1bf9 |
else
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
col += 2;
|
|
Packit |
4e1bf9 |
putchar( ( ( ch >> 6 ) & 7 ) + '0' );
|
|
Packit |
4e1bf9 |
putchar( ( ( ch >> 3 ) & 7 ) + '0' );
|
|
Packit |
4e1bf9 |
putchar( ( ch & 7 ) + '0' );
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
if( !traditional() && ( pflags & GLS ) ) putchar('$');
|
|
Packit |
4e1bf9 |
putchar('\n');
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
/* print a range of lines to stdout */
|
|
Packit |
4e1bf9 |
bool print_lines( int from, const int to, const int pflags )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
line_t * const ep = search_line_node( inc_addr( to ) );
|
|
Packit |
4e1bf9 |
line_t * bp = search_line_node( from );
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
if( !from ) { set_error_msg( "Invalid address" ); return false; }
|
|
Packit |
4e1bf9 |
while( bp != ep )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
const char * const s = get_sbuf_line( bp );
|
|
Packit |
4e1bf9 |
if( !s ) return false;
|
|
Packit |
4e1bf9 |
set_current_addr( from++ );
|
|
Packit |
4e1bf9 |
print_line( s, bp->len, pflags );
|
|
Packit |
4e1bf9 |
bp = bp->q_forw;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
return true;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
/* return the parity of escapes at the end of a string */
|
|
Packit |
4e1bf9 |
static bool trailing_escape( const char * const s, int len )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
bool odd_escape = false;
|
|
Packit |
4e1bf9 |
while( --len >= 0 && s[len] == '\\' ) odd_escape = !odd_escape;
|
|
Packit |
4e1bf9 |
return odd_escape;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
/* If *ibufpp contains an escaped newline, get an extended line (one
|
|
Packit |
4e1bf9 |
with escaped newlines) from stdin.
|
|
Packit |
4e1bf9 |
Return line length in *lenp, including the trailing newline. */
|
|
Packit |
4e1bf9 |
bool get_extended_line( const char ** const ibufpp, int * const lenp,
|
|
Packit |
4e1bf9 |
const bool strip_escaped_newlines )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
static char * buf = 0;
|
|
Packit |
4e1bf9 |
static int bufsz = 0;
|
|
Packit |
4e1bf9 |
int len;
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
for( len = 0; (*ibufpp)[len++] != '\n'; ) ;
|
|
Packit |
4e1bf9 |
if( len < 2 || !trailing_escape( *ibufpp, len - 1 ) )
|
|
Packit |
4e1bf9 |
{ if( lenp ) *lenp = len; return true; }
|
|
Packit |
4e1bf9 |
if( !resize_buffer( &buf, &bufsz, len ) ) return false;
|
|
Packit |
4e1bf9 |
memcpy( buf, *ibufpp, len );
|
|
Packit |
4e1bf9 |
--len; buf[len-1] = '\n'; /* strip trailing esc */
|
|
Packit |
4e1bf9 |
if( strip_escaped_newlines ) --len; /* strip newline */
|
|
Packit |
4e1bf9 |
while( true )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
int len2;
|
|
Packit |
4e1bf9 |
const char * const s = get_stdin_line( &len2 );
|
|
Packit |
4e1bf9 |
if( !s ) return false; /* error */
|
|
Packit |
4e1bf9 |
if( len2 <= 0 ) return false; /* EOF */
|
|
Packit |
4e1bf9 |
if( !resize_buffer( &buf, &bufsz, len + len2 ) ) return false;
|
|
Packit |
4e1bf9 |
memcpy( buf + len, s, len2 );
|
|
Packit |
4e1bf9 |
len += len2;
|
|
Packit |
4e1bf9 |
if( len2 < 2 || !trailing_escape( buf, len - 1 ) ) break;
|
|
Packit |
4e1bf9 |
--len; buf[len-1] = '\n'; /* strip trailing esc */
|
|
Packit |
4e1bf9 |
if( strip_escaped_newlines ) --len; /* strip newline */
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
if( !resize_buffer( &buf, &bufsz, len + 1 ) ) return false;
|
|
Packit |
4e1bf9 |
buf[len] = 0;
|
|
Packit |
4e1bf9 |
*ibufpp = buf;
|
|
Packit |
4e1bf9 |
if( lenp ) *lenp = len;
|
|
Packit |
4e1bf9 |
return true;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
/* Read a line of text from stdin.
|
|
Packit |
4e1bf9 |
Incomplete lines (lacking the trailing newline) are discarded.
|
|
Packit |
4e1bf9 |
Returns pointer to buffer and line size (including trailing newline),
|
|
Packit |
4e1bf9 |
or 0 if error, or *sizep = 0 if EOF */
|
|
Packit |
4e1bf9 |
const char * get_stdin_line( int * const sizep )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
static char * buf = 0;
|
|
Packit |
4e1bf9 |
static int bufsz = 0;
|
|
Packit |
4e1bf9 |
int i = 0;
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
while( true )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
const int c = getchar();
|
|
Packit |
4e1bf9 |
if( !resize_buffer( &buf, &bufsz, i + 2 ) ) { *sizep = 0; return 0; }
|
|
Packit |
4e1bf9 |
if( c == EOF )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
if( ferror( stdin ) )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
show_strerror( "stdin", errno );
|
|
Packit |
4e1bf9 |
set_error_msg( "Cannot read stdin" );
|
|
Packit |
4e1bf9 |
clearerr( stdin );
|
|
Packit |
4e1bf9 |
*sizep = 0; return 0;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
if( feof( stdin ) )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
set_error_msg( "Unexpected end-of-file" );
|
|
Packit |
4e1bf9 |
clearerr( stdin );
|
|
Packit |
4e1bf9 |
buf[0] = 0; *sizep = 0; if( i > 0 ) ++linenum_; /* discard line */
|
|
Packit |
4e1bf9 |
return buf;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
else
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
buf[i++] = c; if( !c ) set_binary(); if( c != '\n' ) continue;
|
|
Packit |
4e1bf9 |
++linenum_; buf[i] = 0; *sizep = i;
|
|
Packit |
4e1bf9 |
return buf;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
/* Read a line of text from a stream.
|
|
Packit |
4e1bf9 |
Returns pointer to buffer and line size (including trailing newline
|
|
Packit |
4e1bf9 |
if it exists and is not added now) */
|
|
Packit |
4e1bf9 |
static const char * read_stream_line( FILE * const fp, int * const sizep,
|
|
Packit |
4e1bf9 |
bool * const newline_addedp )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
static char * buf = 0;
|
|
Packit |
4e1bf9 |
static int bufsz = 0;
|
|
Packit |
4e1bf9 |
int c, i = 0;
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
while( true )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
if( !resize_buffer( &buf, &bufsz, i + 2 ) ) return 0;
|
|
Packit |
4e1bf9 |
c = getc( fp ); if( c == EOF ) break;
|
|
Packit |
4e1bf9 |
buf[i++] = c;
|
|
Packit |
4e1bf9 |
if( !c ) set_binary(); else if( c == '\n' ) break;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
buf[i] = 0;
|
|
Packit |
4e1bf9 |
if( c == EOF )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
if( ferror( fp ) )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
show_strerror( 0, errno );
|
|
Packit |
4e1bf9 |
set_error_msg( "Cannot read input file" );
|
|
Packit |
4e1bf9 |
return 0;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
else if( i )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
buf[i] = '\n'; buf[i+1] = 0; *newline_addedp = true;
|
|
Packit |
4e1bf9 |
if( !isbinary() ) ++i;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
*sizep = i;
|
|
Packit |
4e1bf9 |
return buf;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
/* read a stream into the editor buffer;
|
|
Packit |
4e1bf9 |
return total size of data read, or -1 if error */
|
|
Packit |
4e1bf9 |
static long read_stream( FILE * const fp, const int addr )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
line_t * lp = search_line_node( addr );
|
|
Packit |
4e1bf9 |
undo_t * up = 0;
|
|
Packit |
4e1bf9 |
long total_size = 0;
|
|
Packit |
4e1bf9 |
const bool o_isbinary = isbinary();
|
|
Packit |
4e1bf9 |
const bool appended = ( addr == last_addr() );
|
|
Packit |
4e1bf9 |
const bool o_unterminated_last_line = unterminated_last_line();
|
|
Packit |
4e1bf9 |
bool newline_added = false;
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
set_current_addr( addr );
|
|
Packit |
4e1bf9 |
while( true )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
int size = 0;
|
|
Packit |
4e1bf9 |
const char * const s = read_stream_line( fp, &size, &newline_added );
|
|
Packit |
4e1bf9 |
if( !s ) return -1;
|
|
Packit |
4e1bf9 |
if( size <= 0 ) break;
|
|
Packit |
4e1bf9 |
total_size += size;
|
|
Packit |
4e1bf9 |
disable_interrupts();
|
|
Packit |
4e1bf9 |
if( !put_sbuf_line( s, size + newline_added ) )
|
|
Packit |
4e1bf9 |
{ enable_interrupts(); return -1; }
|
|
Packit |
4e1bf9 |
lp = lp->q_forw;
|
|
Packit |
4e1bf9 |
if( up ) up->tail = lp;
|
|
Packit |
4e1bf9 |
else
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
up = push_undo_atom( UADD, current_addr(), current_addr() );
|
|
Packit |
4e1bf9 |
if( !up ) { enable_interrupts(); return -1; }
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
enable_interrupts();
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
if( addr && appended && total_size && o_unterminated_last_line )
|
|
Packit |
4e1bf9 |
fputs( "Newline inserted\n", stdout ); /* before stream */
|
|
Packit |
4e1bf9 |
else if( newline_added && ( !appended || !isbinary() ) )
|
|
Packit |
4e1bf9 |
fputs( "Newline appended\n", stdout ); /* after stream */
|
|
Packit |
4e1bf9 |
if( !appended && isbinary() && !o_isbinary && newline_added )
|
|
Packit |
4e1bf9 |
++total_size;
|
|
Packit |
4e1bf9 |
if( appended && isbinary() && ( newline_added || total_size == 0 ) )
|
|
Packit |
4e1bf9 |
unterminated_line = search_line_node( last_addr() );
|
|
Packit |
4e1bf9 |
return total_size;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
/* read a named file/pipe into the buffer; return line count, or -1 if error */
|
|
Packit |
4e1bf9 |
int read_file( const char * const filename, const int addr )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
FILE * fp;
|
|
Packit |
4e1bf9 |
long size;
|
|
Packit |
4e1bf9 |
int ret;
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
if( *filename == '!' ) fp = popen( filename + 1, "r" );
|
|
Packit |
4e1bf9 |
else fp = fopen( strip_escapes( filename ), "r" );
|
|
Packit |
4e1bf9 |
if( !fp )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
show_strerror( filename, errno );
|
|
Packit |
4e1bf9 |
set_error_msg( "Cannot open input file" );
|
|
Packit |
4e1bf9 |
return -1;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
size = read_stream( fp, addr );
|
|
Packit |
4e1bf9 |
if( *filename == '!' ) ret = pclose( fp ); else ret = fclose( fp );
|
|
Packit |
4e1bf9 |
if( size < 0 ) return -1;
|
|
Packit |
4e1bf9 |
if( ret != 0 )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
show_strerror( filename, errno );
|
|
Packit |
4e1bf9 |
set_error_msg( "Cannot close input file" );
|
|
Packit |
4e1bf9 |
return -1;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
if( !scripted() ) printf( "%lu\n", size );
|
|
Packit |
4e1bf9 |
return current_addr() - addr;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
/* write a range of lines to a stream */
|
|
Packit |
4e1bf9 |
static long write_stream( FILE * const fp, int from, const int to )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
line_t * lp = search_line_node( from );
|
|
Packit |
4e1bf9 |
long size = 0;
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
while( from && from <= to )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
int len;
|
|
Packit |
4e1bf9 |
char * p = get_sbuf_line( lp );
|
|
Packit |
4e1bf9 |
if( !p ) return -1;
|
|
Packit |
4e1bf9 |
len = lp->len;
|
|
Packit |
4e1bf9 |
if( from != last_addr() || !isbinary() || !unterminated_last_line() )
|
|
Packit |
4e1bf9 |
p[len++] = '\n';
|
|
Packit |
4e1bf9 |
size += len;
|
|
Packit |
4e1bf9 |
while( --len >= 0 )
|
|
Packit |
4e1bf9 |
if( fputc( *p++, fp ) == EOF )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
show_strerror( 0, errno );
|
|
Packit |
4e1bf9 |
set_error_msg( "Cannot write file" );
|
|
Packit |
4e1bf9 |
return -1;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
++from; lp = lp->q_forw;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
return size;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
/* write a range of lines to a named file/pipe; return line count */
|
|
Packit |
4e1bf9 |
int write_file( const char * const filename, const char * const mode,
|
|
Packit |
4e1bf9 |
const int from, const int to )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
FILE * fp;
|
|
Packit |
4e1bf9 |
long size;
|
|
Packit |
4e1bf9 |
int ret;
|
|
Packit |
4e1bf9 |
|
|
Packit |
4e1bf9 |
if( *filename == '!' ) fp = popen( filename + 1, "w" );
|
|
Packit |
4e1bf9 |
else fp = fopen( strip_escapes( filename ), mode );
|
|
Packit |
4e1bf9 |
if( !fp )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
show_strerror( filename, errno );
|
|
Packit |
4e1bf9 |
set_error_msg( "Cannot open output file" );
|
|
Packit |
4e1bf9 |
return -1;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
size = write_stream( fp, from, to );
|
|
Packit |
4e1bf9 |
if( *filename == '!' ) ret = pclose( fp ); else ret = fclose( fp );
|
|
Packit |
4e1bf9 |
if( size < 0 ) return -1;
|
|
Packit |
4e1bf9 |
if( ret != 0 )
|
|
Packit |
4e1bf9 |
{
|
|
Packit |
4e1bf9 |
show_strerror( filename, errno );
|
|
Packit |
4e1bf9 |
set_error_msg( "Cannot close output file" );
|
|
Packit |
4e1bf9 |
return -1;
|
|
Packit |
4e1bf9 |
}
|
|
Packit |
4e1bf9 |
if( !scripted() ) printf( "%lu\n", size );
|
|
Packit |
4e1bf9 |
return ( from && from <= to ) ? to - from + 1 : 0;
|
|
Packit |
4e1bf9 |
}
|