/* * chkWrite - write checkpoint data */ static bool chkWrite( void *buff, unsigned *size ) { unsigned bytes; switch( isWhere ) { case ON_DISK: if( *size >= 0x1000 ) { *size = 0x0800; } bytes = *size << 4; if( TinyWrite( fileHandle, buff, bytes) != bytes ) { return( false ); } return( true ); #ifndef NOEMS case IN_EMS: memBlockWrite( &EMSBlockWrite, buff, size ); return( true ); #endif #ifndef NOXMS case IN_XMS: memBlockWrite( &XMSBlockWrite, buff, size ); return( true ); #endif } } /* chkWrite */
size_t LocalWrite( sys_handle filehndl, const void *ptr, size_t len ) { tiny_ret_t ret; size_t total; unsigned piece_len; unsigned write_len; piece_len = INT_MAX; total = 0; while( len > 0 ) { if( piece_len > len ) piece_len = (unsigned)len; ret = TinyWrite( filehndl, ptr, piece_len ); if( TINY_ERROR( ret ) ) { StashErrCode( TINY_INFO( ret ), OP_LOCAL ); return( ERR_RETURN ); } write_len = TINY_INFO( ret ); total += write_len; if( write_len != piece_len ) break; ptr = (char *)ptr + write_len; len -= write_len; } return( total ); }
static tiny_ret_t __TinyWrite( int handle, const void *buffer, unsigned len ) { unsigned total = 0; unsigned writamt; tiny_ret_t rc; while( len > 0 ) { if( len > MAXBUFF ) { writamt = MAXBUFF; } else { writamt = len; } rc = TinyWrite( handle, buffer, writamt ); if( TINY_ERROR( rc ) ) return( rc ); total += TINY_LINFO( rc ); if( TINY_LINFO( rc ) != writamt ) return( total ); len -= writamt; buffer = ((const char *)buffer) + writamt; } return( total ); }
int out( char * str ) { char *p; p = str; while( *p ) ++p; TinyWrite( 1, str, p - str ); return 0; }
trap_retval ReqFile_write_console( void ) { tiny_ret_t rc; file_write_console_ret *ret; ret = GetOutPtr( 0 ); rc = TinyWrite( TINY_ERR, GetInPtr( sizeof( file_write_console_req ) ), ( GetTotalSize() - sizeof( file_write_console_req ) ) ); ret->len = TINY_INFO( rc ); ret->err = TINY_ERROR( rc ) ? TINY_INFO( rc ) : 0; return( sizeof( *ret ) ); }
unsigned LocalWrite( sys_handle filehndl, const void *ptr, unsigned len ) { tiny_ret_t ret; ret = TinyWrite( filehndl, ptr, len ); if( TINY_ERROR( ret ) ) { StashErrCode( TINY_INFO( ret ), OP_LOCAL ); return( ERR_RETURN ); } return( TINY_INFO( ret ) ); }
trap_retval ReqFile_write( void ) { tiny_ret_t rc; file_write_req *acc; file_write_ret *ret; acc = GetInPtr( 0 ); ret = GetOutPtr( 0 ); rc = TinyWrite( TRPH2LH( acc ), GetInPtr( sizeof( *acc ) ), ( GetTotalSize() - sizeof( *acc ) ) ); ret->len = TINY_INFO( rc ); ret->err = TINY_ERROR( rc ) ? TINY_INFO( rc ) : 0; return( sizeof( *ret ) ); }
static int os_write( int handle, const void *buffer, unsigned len, unsigned *amt ) /********************************************************************************/ { #ifdef DEFAULT_WINDOWING LPWDATA res; #endif #if defined(__NT__) HANDLE h; int rc; #else tiny_ret_t rc; #endif rc = 0; #ifdef DEFAULT_WINDOWING if( _WindowsStdout != 0 && (res = _WindowsIsWindowedHandle( handle )) != 0 ) { *amt = _WindowsStdout( res, buffer, len ); } else #endif { #if defined(__NT__) h = __getOSHandle( handle ); if( !WriteFile( h, (LPCVOID)buffer, (DWORD)len, (LPDWORD)amt, NULL ) ) { rc = __set_errno_nt(); } #elif defined(__OS2_286__) rc = DosWrite( handle, (PVOID)buffer, (USHORT)len, (PUSHORT)amt ); #elif defined(__OS2__) rc = DosWrite( handle, (PVOID)buffer, (ULONG)len, (PULONG)amt ); #else rc = TinyWrite( handle, buffer, len ); *amt = TINY_LINFO( rc ); if( TINY_OK( rc ) ) { rc = 0; } #endif } #if !defined(__NT__) if( TINY_ERROR( rc ) ) { rc = __set_errno_dos( TINY_INFO( rc ) ); } #endif if( *amt != len ) { rc = ENOSPC; __set_errno( rc ); } return( rc ); }
static int os_write( int handle, const void *buffer, unsigned len, unsigned *amt ) /********************************************************************************/ { int rc; #ifdef DEFAULT_WINDOWING LPWDATA res; #endif #if defined(__NT__) HANDLE h; #elif defined(__OS2__) APIRET rc1; #else tiny_ret_t rc1; #endif rc = 0; #ifdef DEFAULT_WINDOWING if( _WindowsStdout != NULL && (res = _WindowsIsWindowedHandle( handle )) != NULL ) { *amt = _WindowsStdout( res, buffer, len ); } else #endif { #if defined(__NT__) h = __getOSHandle( handle ); if( !WriteFile( h, (LPCVOID)buffer, (DWORD)len, (LPDWORD)amt, NULL ) ) { return( __set_errno_nt() ); } #elif defined(__OS2__) rc1 = DosWrite( handle, (PVOID)buffer, (OS_UINT)len, (OS_PUINT)amt ); if( rc1 ) { return( __set_errno_dos( rc1 ) ); } #else rc1 = TinyWrite( handle, buffer, len ); if( TINY_ERROR( rc1 ) ) { return( __set_errno_dos( TINY_INFO( rc1 ) ) ); } *amt = TINY_LINFO( rc1 ); #endif } if( *amt != len ) { rc = ENOSPC; _RWD_errno = rc; } return( rc ); }
static unsigned TestWrite( f_handle file, void *buffer, unsigned len, char *name ) /*****************************************************************************/ { tiny_ret_t h; char rc_buff[RESOURCE_MAX_SIZE]; CheckBreak(); if( len == 0 ) return( 0 ); h = TinyWrite( file, buffer, len ); if( name != NULL ) { if( TINY_ERROR( h ) ) { LnkMsg( ERR+MSG_IO_PROBLEM, "12", name, QErrMsg( TINY_INFO( h ) ) ); return( ~0 ); } else if( TINY_INFO( h ) != len ) { if( name != NULL ) { Msg_Get( MSG_IOERRLIST_7, rc_buff ); LnkMsg( (FTL+MSG_IO_PROBLEM) & ~OUT_MAP, "12", name, rc_buff ); } } } return( TINY_INFO(h) ); }
static int __F_NAME(__sopen,__wsopen)( const CHAR_TYPE *name, int mode, int shflag, va_list args ) { int rwmode; int handle; int attr; int permission; unsigned iomode_flags; tiny_ret_t rc; char dummy; #ifdef __WIDECHAR__ char mbName[MB_CUR_MAX * _MAX_PATH]; /* single-byte char */ #endif handle = -1; rc = 0; while( *name == STRING( ' ' ) ) ++name; #ifdef __WIDECHAR__ /*** If necessary, convert the wide filename to multibyte form ***/ if( wcstombs( mbName, name, sizeof( mbName ) ) == -1 ) { mbName[0] = '\0'; } #endif rwmode = mode & ( O_RDONLY | O_WRONLY | O_RDWR | O_NOINHERIT ); if( _dos_open( __F_NAME(name,mbName), rwmode | shflag, &handle ) == 0 ) { if( handle >= __NFiles ) { TinyClose( handle ); __set_errno( EMFILE ); return( -1 ); } } /* 17-apr-90 05-sep-91 */ if( (mode & (O_RDONLY | O_WRONLY | O_RDWR)) != O_RDONLY ) { if( handle != -1 ) { if( ! isatty( handle ) ) { /* if not a device */ #if 0 rc = TinyAccess( name, 0 ); /* check for existence */ if( TINY_ERROR( rc ) ) { /* file does not exist */ TinyClose( handle ); /* close whatever file we got */ handle = -1; } else if( mode & O_EXCL ) { /* must not exist */ #else /* Don't need to do the access check, since the file was opened and therefore must exist (TinyOpen can't create a file). We don't want to do the check because there are classes of items in the file system namespace that are not devices, but the TinyAccess will fail on (e.g. named pipes). */ /* must not exist if O_CREAT specified */ if( (mode & O_EXCL) && (mode & O_CREAT) ) { #endif TinyClose( handle ); __set_errno( EEXIST ); return( -1 ); } else if( mode & O_TRUNC ) { /* truncate file */ rc = TinyWrite( handle, &dummy, 0 ); if( TINY_ERROR( rc ) ) { TinyClose( handle ); return( __set_errno_dos( TINY_INFO( rc ) ) ); } } } } } if( handle == -1 ) { /* could not open */ if( (mode & O_CREAT) == 0 || _RWD_doserrno != E_nofile ) { return( -1 ); } /* creating the file */ permission = va_arg( args, int ); va_end( args ); if( permission == 0 ) permission = S_IWRITE | S_IREAD; permission &= ~_RWD_umaskval; /* 05-jan-95 */ attr = 0; if(( permission & S_IWRITE) == 0 ) attr = _A_RDONLY; #if 0 /* remove this support because it is not consistently available */ if( _RWD_osmajor >= 5 #ifdef __DOS_EXT__ && !_IsFlashTek() && !_IsRational() #endif ) { /* this function is only available in version DOS 5 and up */ /* this new way was added to handle the case of creating a */ /* new file with read-only access, but with a writeable */ /* file handle */ #ifdef __WIDECHAR__ rc = TinyCreateEx( mbName, rwmode|shflag, attr, TIO_OPEN ); #else rc = TinyCreateEx( name, rwmode|shflag, attr, TIO_OPEN ); #endif if( TINY_ERROR( rc ) ) { return( __set_errno_dos( TINY_INFO( rc ) ) ); } handle = TINY_INFO( rc ); } else #endif { /* do it the old way */ if( _dos_creat( __F_NAME(name,mbName), attr, &handle ) ) { return( -1 ); } if( handle >= __NFiles ) { TinyClose( handle ); __set_errno( EMFILE ); return( -1 ); } /* 21-nov-90 AFS: the file is created so now the file must be */ /* opened with the correct share permissions */ if( shflag != 0 ) { rc = TinyClose( handle ); if( TINY_ERROR( rc ) ) { return( __set_errno_dos( TINY_INFO( rc ) ) ); } if( _dos_open( __F_NAME(name,mbName), rwmode | shflag, &handle ) ) { return( -1 ); } /* handle does not equal -1 now */ } } } iomode_flags = __GetIOMode( handle ); iomode_flags &= ~(_READ|_WRITE|_APPEND|_BINARY); /* 11-aug-88 */ if( isatty( handle ) ) iomode_flags |= _ISTTY; rwmode &= ~O_NOINHERIT; if( rwmode == O_RDWR ) iomode_flags |= _READ | _WRITE; if( rwmode == O_RDONLY) iomode_flags |= _READ; if( rwmode == O_WRONLY) iomode_flags |= _WRITE; if( mode & O_APPEND ) iomode_flags |= _APPEND; if( mode & (O_BINARY|O_TEXT) ) { if( mode & O_BINARY ) iomode_flags |= _BINARY; } else { if( _RWD_fmode == O_BINARY ) iomode_flags |= _BINARY; } __SetIOMode( handle, iomode_flags ); #ifdef DEFAULT_WINDOWING if( _WindowsNewWindow != 0 ) { if( !__F_NAME(stricmp,wcscmp)( name, STRING( "con" ) ) ) { _WindowsNewWindow( NULL, handle, -1 ); } } #endif return( handle ); } #if 0 /* couldn't find any user; please re-enable if it's necessary */ #ifndef __WIDECHAR__ /* compile one version only */ int __set_binary( int handle ) { unsigned iomode_flags; __ChkTTYIOMode( handle ); iomode_flags = __GetIOMode( handle ); iomode_flags |= _BINARY; __SetIOMode( handle, iomode_flags ); if( iomode_flags & _ISTTY ) { tiny_ret_t rc; rc = TinyGetDeviceInfo( handle ); if( TINY_ERROR( rc ) ) { return( __set_errno_dos( TINY_INFO( rc ) ) ); } rc = TinySetDeviceInfo( handle, TINY_INFO(rc) | TIO_CTL_RAW ); if( TINY_ERROR( rc ) ) { return( __set_errno_dos( TINY_INFO( rc ) ) ); } } return( 0 ); }
bool CheckPointMem( unsigned max, char *f_buff ) { dos_mem_block *mem; dos_mem_block *start; dos_mem_block *end; dos_mem_block *next; dos_mem_block *chk; tiny_ret_t rc; tiny_handle_t hdl; unsigned size; unsigned bytes; unsigned psp; char *p; if( max == 0 ) return( FALSE ); ChkFile = f_buff; psp = TinyGetPSP(); start = MK_FP( psp - 1, 0 ); while( start->owner == psp ) { if( start->chain == END_OF_CHAIN ) return( FALSE ); // start = NEXT_BLOCK( start ); start = MK_FP( (FP_SEG( start ) + (start)->size + 1), 0 ); } mem = start; for( ;; ) { if( mem->owner == 0 && mem->size >= max ) return( FALSE ); if( mem->chain == END_OF_CHAIN ) break; // mem = NEXT_BLOCK( mem ); mem = MK_FP( (FP_SEG( mem ) + (mem)->size + 1), 0 ); } // end = NEXT_BLOCK( mem ); end = MK_FP( (FP_SEG( mem ) + (mem)->size + 1), 0 ); size = FP_SEG( end ) - FP_SEG( start ); if( size < 0x1000 ) return( FALSE ); *f_buff++ = TinyGetCurrDrive() + 'A'; *f_buff++ = ':'; *f_buff++ = '\\'; rc = TinyFarGetCWDir( (char __far *)f_buff, 0 ); if( TINY_ERROR( rc ) ) return( FALSE ); while( *f_buff != 0 ) ++f_buff; if( f_buff[-1] == '\\' ) { --f_buff; } else { *f_buff++ = '\\'; } for( p = CHECK_FILE; *f_buff = *p; ++p, ++f_buff ) {} rc = TinyCreate( ChkFile, TIO_NORMAL ); if( TINY_ERROR( rc ) ) return( FALSE ); hdl = TINY_INFO( rc ); if( size > max ) size = max; chk = MK_FP( FP_SEG( end ) - size - 1, 0 ); mem = start; for( ;; ) { // next = NEXT_BLOCK( mem ); next = MK_FP( (FP_SEG( mem ) + (mem)->size + 1), 0 ); if( FP_SEG( next ) > FP_SEG( chk ) ) break; mem = next; } if( !PUT_ITEM( mem ) || !PUT_ITEM( *mem ) || !PUT_ITEM( chk ) ) { TinyClose( hdl ); Cleanup(); return( FALSE ); } next = chk; while( FP_SEG( next ) < FP_SEG( end ) ) { size = FP_SEG( end ) - FP_SEG( next ); if( size >= 0x1000 ) size = 0x0800; bytes = size << 4; if( TinyWrite( hdl, next, bytes ) != bytes ) { TinyClose( hdl ); Cleanup(); return( FALSE ); } next = MK_FP( FP_SEG( next ) + size, 0 ); } TinyClose( hdl ); mem->chain = MEMORY_BLOCK; mem->size = FP_SEG( chk ) - FP_SEG( mem ) - 1; chk->size = FP_SEG( end ) - FP_SEG( chk ) - 1; chk->chain = END_OF_CHAIN; chk->owner = 0; return( TRUE ); }
int __qwrite( int handle, const void *buffer, unsigned len ) { int atomic; #if defined(__NT__) DWORD len_written; HANDLE h; int error; #elif defined(__WARP__) ULONG len_written; #elif defined(__OS2_286__) USHORT len_written; #else unsigned len_written; #endif #if !defined(__NT__) tiny_ret_t rc; #endif __handle_check( handle, -1 ); #if defined(__NT__) h = __getOSHandle( handle ); #endif atomic = 0; if( __GetIOMode( handle ) & _APPEND ) { _AccessFileH( handle ); atomic = 1; #if defined(__NT__) if( SetFilePointer( h, 0, NULL, FILE_END ) == -1 ) { error = GetLastError(); _ReleaseFileH( handle ); return( __set_errno_dos( error ) ); } #elif defined(__OS2__) { unsigned long dummy; rc = DosChgFilePtr( handle, 0L, SEEK_END, &dummy ); } #else rc = TinySeek( handle, 0L, SEEK_END ); #endif #if !defined(__NT__) if( TINY_ERROR( rc ) ) { _ReleaseFileH( handle ); return( __set_errno_dos( TINY_INFO( rc ) ) ); } #endif } #ifdef DEFAULT_WINDOWING if( _WindowsStdout != 0 ) { LPWDATA res; res = _WindowsIsWindowedHandle( handle ); if( res ) { int rt; rt = _WindowsStdout( res, buffer, len ); return( rt ); } } #endif #if defined(__NT__) if( !WriteFile( h, buffer, len, &len_written, NULL ) ) { error = GetLastError(); if( atomic == 1 ) { _ReleaseFileH( handle ); } return( __set_errno_dos( error ) ); } #elif defined(__OS2__) rc = DosWrite( handle, (PVOID)buffer, len, &len_written ); #elif defined(__WINDOWS_386__) rc = __TinyWrite( handle, buffer, len ); len_written = TINY_LINFO( rc ); #else rc = TinyWrite( handle, buffer, len ); len_written = TINY_LINFO( rc ); #endif #if !defined(__NT__) if( TINY_ERROR( rc ) ) { if( atomic == 1 ) { _ReleaseFileH( handle ); } return( __set_errno_dos( TINY_INFO( rc ) ) ); } #endif if( len_written != len ) { __set_errno( ENOSPC ); } if( atomic == 1 ) { _ReleaseFileH( handle ); } return( len_written ); }
unsigned ReqProg_load( void ) { char buffer[160]; char *src; char *dst; char *name; char *endparm; char *err; tiny_ret_t rc; prog_load_ret *ret; unsigned_16 len; SaveVectors( OrigVectors ); _DBG_EnterFunc( "AccLoadProg()" ); ret = GetOutPtr( 0 ); src = name = GetInPtr( sizeof( prog_load_req ) ); rc = FindFilePath( src, buffer, DosXExtList ); endparm = LinkParm; while( *endparm++ != '\0' ) {} // skip program name strcpy( endparm, buffer ); err = RemoteLink( LinkParm, 0 ); if( err != NULL ) { _DBG_Writeln( "Can't RemoteLink" ); TinyWrite( TINY_ERR, err, strlen( err ) ); LoadError = err; ret->err = 1; len = 0; } else { if( TINY_OK( rc ) ) { while( *src++ != '\0' ) {} len = GetTotalSize() - ( src - name ) - sizeof( prog_load_req ); dst = (char *)buffer; while( *dst++ != '\0' ) {}; memcpy( dst, src, len ); dst += len; _DBG_Writeln( "StartPacket" ); StartPacket(); _DBG_Writeln( "AddPacket" ); AddPacket( sizeof( prog_load_req ), In_Mx_Ptr[0].ptr ); _DBG_Writeln( "AddPacket" ); AddPacket( dst - buffer, buffer ); _DBG_Writeln( "PutPacket" ); PutPacket(); _DBG_Writeln( "GetPacket" ); len = GetPacket(); _DBG_Writeln( "RemovePacket" ); RemovePacket( sizeof( *ret ), ret ); } else { len = DoAccess(); } _DBG_Writeln( "Linked --" ); if( ret->err != 0 ) { get_err_text_req erracc; prog_kill_req killacc; int msg_len; _DBG_Writeln( "loadret->errcode != 0" ); if( LoadError == NULL ) { _DBG_Writeln( "making a REQ_GET_ERR_TEXT request" ); erracc.req = REQ_GET_ERR_TEXT; erracc.err = ret->err; _DBG_Writeln( "StartPacket" ); StartPacket(); _DBG_Writeln( "AddPacket" ); AddPacket( sizeof( erracc ), &erracc ); _DBG_Writeln( "PutPacket" ); PutPacket(); _DBG_Writeln( "GetPacket" ); msg_len = GetPacket(); _DBG_Writeln( "RemovePacket" ); RemovePacket( msg_len, FailMsg ); _DBG_Write( "FailMsg : " ); _DBG_NoTabWriteln( FailMsg ); LoadError = FailMsg; } _DBG_Writeln( "making a REQ_PROG_KILL request" ); killacc.req = REQ_PROG_KILL; _DBG_Writeln( "StartPacket" ); StartPacket(); _DBG_Writeln( "AddPacket" ); AddPacket( sizeof( killacc ), &killacc ); _DBG_Writeln( "PutPacket" ); PutPacket(); _DBG_Writeln( "GetPacket" ); GetPacket(); //RemovePacket( msg_len, &erracc ); RemoteUnLink(); TaskLoaded = FALSE; } } if( ret->err == 0 ) { _DBG_Writeln( "loadret->error_code == 0" ); TaskLoaded = TRUE; } SaveVectors( LoadVectors ); SaveVectors( CurrVectors ); _DBG_ExitFunc( "AccLoadProg()" ); return( len ); }
trap_retval ReqProg_load( void ) { char buffer[160]; char *src; char *dst; char *name; char *endparm; const char *err; tiny_ret_t rc; prog_load_ret *ret; trap_elen len; SaveVectors( OrigVectors ); _DBG_EnterFunc( "AccLoadProg()" ); ret = GetOutPtr( 0 ); src = name = GetInPtr( sizeof( prog_load_req ) ); rc = FindProgFile( src, buffer, DosExtList ); endparm = LinkParms; while( *endparm++ != '\0' ) {} // skip trap parameters strcpy( endparm, buffer ); // add command line // result is as follow // "trap parameters string"+"\0"+"command line string"+"\0" err = RemoteLink( LinkParms, false ); if( err != NULL ) { _DBG_Writeln( "Can't RemoteLink" ); TinyWrite( TINY_ERR, err, strlen( err ) ); LoadError = err; ret->err = 1; len = 0; } else { if( TINY_OK( rc ) ) { while( *src++ != '\0' ) {} len = GetTotalSize() - ( src - name ) - sizeof( prog_load_req ); dst = (char *)buffer; while( *dst++ != '\0' ) {}; memcpy( dst, src, len ); dst += len; _DBG_Writeln( "StartPacket" ); StartPacket(); _DBG_Writeln( "AddPacket" ); AddPacket( In_Mx_Ptr[0].ptr, sizeof( prog_load_req ) ); _DBG_Writeln( "AddPacket" ); AddPacket( buffer, dst - buffer ); _DBG_Writeln( "PutPacket" ); PutPacket(); _DBG_Writeln( "GetPacket" ); len = GetPacket(); _DBG_Writeln( "RemovePacket" ); RemovePacket( ret, sizeof( *ret ) ); } else { len = DoAccess(); } _DBG_Writeln( "Linked --" ); if( ret->err != 0 ) { get_err_text_req erracc; prog_kill_req killacc; trap_elen msg_len; _DBG_Writeln( "loadret->errcode != 0" ); if( LoadError == NULL ) { _DBG_Writeln( "making a REQ_GET_ERR_TEXT request" ); erracc.req = REQ_GET_ERR_TEXT; erracc.err = ret->err; _DBG_Writeln( "StartPacket" ); StartPacket(); _DBG_Writeln( "AddPacket" ); AddPacket( &erracc, sizeof( erracc ) ); _DBG_Writeln( "PutPacket" ); PutPacket(); _DBG_Writeln( "GetPacket" ); msg_len = GetPacket(); _DBG_Writeln( "RemovePacket" ); RemovePacket( FailMsg, msg_len ); _DBG_Write( "FailMsg : " ); _DBG_NoTabWriteln( FailMsg ); LoadError = FailMsg; } _DBG_Writeln( "making a REQ_PROG_KILL request" ); killacc.req = REQ_PROG_KILL; _DBG_Writeln( "StartPacket" ); StartPacket(); _DBG_Writeln( "AddPacket" ); AddPacket( &killacc, sizeof( killacc ) ); _DBG_Writeln( "PutPacket" ); PutPacket(); _DBG_Writeln( "GetPacket" ); GetPacket(); //RemovePacket( &erracc, msg_len ); RemoteUnLink(); TaskLoaded = false; } } if( ret->err == 0 ) { _DBG_Writeln( "loadret->error_code == 0" ); TaskLoaded = true; } SaveVectors( LoadVectors ); SaveVectors( CurrVectors ); _DBG_ExitFunc( "AccLoadProg()" ); return( len ); }
void Output( const char *str ) { TinyWrite( TINY_ERR, str, strlen( str ) ); }