/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// file: chuck_otf.cpp// desc: on-the-fly programming utilities//// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)// date: Autumn 2004//-----------------------------------------------------------------------------#include "chuck_otf.h"#include "chuck_compile.h"#include "chuck_errmsg.h"#include "util_math.h"#include "util_thread.h"#include "util_string.h"#include "util_platforms.h" #include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <signal.h>#include <time.h> #ifndef __PLATFORM_WIN32__#include <unistd.h>#else // 2022 QTSIN#include <winsock2.h>#include <ws2tcpip.h>#include <windows.h>#endif using namespace std; // log levelt_CKUINT g_otf_log = CK_LOG_INFO; //-----------------------------------------------------------------------------// name: otf_hton( )// desc: ...//-----------------------------------------------------------------------------void otf_hton( Net_Msg * msg ){ msg->header = htonl( msg->header ); msg->type = htonl( msg->type ); msg->param = htonl( msg->param ); msg->param2 = htonl( msg->param2 ); msg->param3 = htonl( msg->param3 ); msg->length = htonl( msg->length );} //-----------------------------------------------------------------------------// name: otf_ntoh( )// desc: ...//-----------------------------------------------------------------------------void otf_ntoh( Net_Msg * msg ){ msg->header = ntohl( msg->header ); msg->type = ntohl( msg->type ); msg->param = ntohl( msg->param ); msg->param2 = ntohl( msg->param2 ); msg->param3 = ntohl( msg->param3 ); msg->length = ntohl( msg->length );} //-----------------------------------------------------------------------------// name: recv_file()// desc: ...//-----------------------------------------------------------------------------FILE * recv_file( const Net_Msg & msg, ck_socket sock ){ Net_Msg buf; // what is left // t_CKUINT left = msg.param2; // make a temp file FILE * fd = ck_tmpfile(); // check if successful if( !fd ) { EM_error2( 0, "OTF nable to create temp file, skipping..." ); return NULL; } do { // msg if( !ck_recv( sock, (char *)&buf, sizeof(buf) ) ) goto error; otf_ntoh( &buf ); // write fwrite( buf.buffer, sizeof(char), buf.length, fd ); }while( buf.param2 > 0 ); // check for error if( buf.param2 == NET_ERROR ) { // this was a problem EM_log( CK_LOG_INFO, "(via otf): received error flag, dropping..." ); // done goto error; } return fd; error: fclose( fd ); fd = NULL; return NULL;} //-----------------------------------------------------------------------------// name: otf_process_msg()// desc: ...//-----------------------------------------------------------------------------t_CKUINT otf_process_msg( Chuck_VM * vm, Chuck_Compiler * compiler, Net_Msg * msg, t_CKBOOL immediate, void * data ){ Chuck_Msg * cmd = new Chuck_Msg; Chuck_VM_Code * code = NULL; FILE * fd = NULL; t_CKUINT ret = 0; // CK_FPRINTF_STDERR( "UDP message recv...\n" ); if( msg->type == MSG_REPLACE || msg->type == MSG_ADD ) { string filename; vector<string> args; // parse out command line arguments if( !extract_args( msg->buffer, filename, args ) ) { // error CK_FPRINTF_STDERR( "[chuck]: malformed filename with argument list...\n" ); CK_FPRINTF_STDERR( " --> '%s'", msg->buffer ); SAFE_DELETE(cmd); goto cleanup; } // copy de-escaped filename strcpy( msg->buffer, filename.c_str() ); // copy args if needed if( args.size() > 0 ) { cmd->args = new vector<string>; *(cmd->args) = args; } // see if entire file is on the way if( msg->param2 && msg->param2 != NET_ERROR ) { fd = recv_file( *msg, (ck_socket)data ); if( !fd ) { CK_FPRINTF_STDERR( "[chuck]: incoming source transfer '%s' failed...\n", mini(msg->buffer) ); SAFE_DELETE(cmd); goto cleanup; } } // construct full path to be associated with the file so me.sourceDir() works // (added 1.3.5.2) std::string full_path = get_full_path( msg->buffer ); // special FILE descriptor mode; set autoClose to true compiler->set_file2parse( fd, TRUE ); // parse, type-check, and emit if( !compiler->go( msg->buffer, full_path ) ) { SAFE_DELETE(cmd); goto cleanup; } // get the code code = compiler->output(); // name it code->name += string(msg->buffer); // set the flags for the command cmd->type = msg->type; cmd->code = code; if( msg->type == MSG_REPLACE ) cmd->param = msg->param; } else if( msg->type == MSG_STATUS || msg->type == MSG_REMOVE || msg->type == MSG_REMOVEALL || msg->type == MSG_EXIT || msg->type == MSG_TIME || msg->type == MSG_RESET_ID || msg->type == MSG_CLEARVM ) { cmd->type = msg->type; cmd->param = msg->param; } else if( msg->type == MSG_ABORT ) { // halt and clear current shred vm->abort_current_shred(); // short circuit ret = 1; SAFE_DELETE(cmd); goto cleanup; } else { CK_FPRINTF_STDERR( "[chuck]: unrecognized incoming command from network: '%li'\n", cmd->type ); SAFE_DELETE(cmd); goto cleanup; } // immediate if( immediate ) ret = vm->process_msg( cmd ); else { // queue message vm->queue_msg( cmd, 1 ); // return code ret = 1; } cleanup: // close file handle if( fd ) fclose( fd ); return ret;} //-----------------------------------------------------------------------------// name: otf_send_file()// desc: ...//-----------------------------------------------------------------------------t_CKINT otf_send_file( const char * fname, Net_Msg & msg, const char * op, ck_socket dest ){ FILE * fd = NULL; struct stat fs; string filename; vector<string> args; string buf; // parse out command line arguments if( !extract_args( fname, filename, args ) ) { // error CK_FPRINTF_STDERR( "[chuck]: malformed filename + argument list...\n" ); CK_FPRINTF_STDERR( " --> '%s'", fname ); return FALSE; } // filename and any args strcpy( msg.buffer, fname ); // test it buf = filename; fd = ck_openFileAutoExt( buf, ".ck" ); if( !fd ) { CK_FPRINTF_STDERR( "[chuck]: cannot open file '%s' for [%s]...\n", filename.c_str(), op ); return FALSE; } if( !chuck_parse( filename ) ) { CK_FPRINTF_STDERR( "[chuck]: skipping file '%s' for [%s]...\n", filename.c_str(), op ); fclose( fd ); return FALSE; } // stat it memset( &fs, 0, sizeof(fs) ); stat( buf.c_str(), &fs ); fseek( fd, 0, SEEK_SET ); // log EM_log( CK_LOG_INFO, "sending TCP file %s, size=%d", filename.c_str(), (t_CKUINT)fs.st_size ); EM_pushlog(); // send the first packet msg.param2 = (t_CKUINT)fs.st_size; msg.length = 0; otf_hton( &msg ); // go ck_send( dest, (char *)&msg, sizeof(msg) ); // send the whole thing t_CKUINT left = (t_CKUINT)fs.st_size; while( left ) { // log EM_log( CK_LOG_FINER, "%03d bytes left ... ", left ); // amount to send msg.length = left > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : left; // read msg.param3 = fread( msg.buffer, sizeof(char), msg.length, fd ); // check for error if( !msg.param3 ) { // error encountered CK_FPRINTF_STDERR( "[chuck]: error while reading '%s'...\n", filename.c_str() ); // mark done left = 0; // error flag msg.param2 = NET_ERROR; } else { // amount left left -= msg.param3; // what's left msg.param2 = left; } // log EM_log( CK_LOG_FINER, "sending buffer %03d length %03d...", msg.param3, msg.length ); // send it otf_hton( &msg ); ck_send( dest, (char *)&msg, sizeof(msg) ); } // pop log EM_poplog(); // close fclose( fd ); return TRUE;} //-----------------------------------------------------------------------------// name: otf_send_connect()// desc: ...//-----------------------------------------------------------------------------ck_socket otf_send_connect( const char * host, t_CKINT port ){ // log EM_log( CK_LOG_INFO, "otf connect: %s:%i", host, port ); ck_socket sock = ck_tcp_create( 0 ); if( !sock ) { CK_FPRINTF_STDERR( "[chuck]: cannot open socket to send command...\n" ); return NULL; } if( strcmp( host, "127.0.0.1" ) ) EM_log( g_otf_log, "connecting to %s on port %i via TCP...", host, port ); if( !ck_connect( sock, host, (int)port ) ) { CK_FPRINTF_STDERR( "cannot open TCP socket on %s:%i...\n", host, port ); ck_close( sock ); return NULL; } ck_send_timeout( sock, 0, 2000000 ); return sock;} //-----------------------------------------------------------------------------// name: otf_send_cmd()// desc: ...//-----------------------------------------------------------------------------t_CKINT otf_send_cmd( t_CKINT argc, const char ** argv, t_CKINT & i, const char * host, t_CKINT port, t_CKINT * is_otf ){ Net_Msg msg; // REFACTOR-2017 TODO: wat is global sigpipe mode// g_sigpipe_mode = 1; int tasks_total = 0, tasks_done = 0; ck_socket dest = NULL; if( is_otf ) *is_otf = TRUE; // log EM_log( CK_LOG_INFO, "examining otf command '%s'...", argv[i] ); if( !strcmp( argv[i], "--add" ) || !strcmp( argv[i], "+" ) ) { if( ++i >= argc ) { CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [add]...\n" ); goto error; } if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); do { // log EM_log( CK_LOG_INFO, "sending file:args '%s' for ADD...", mini(argv[i]) ); msg.type = MSG_ADD; msg.param = 1; tasks_done += otf_send_file( argv[i], msg, "add", dest ); tasks_total++; } while( ++i < argc ); // log EM_poplog(); if( !tasks_done ) goto error; } else if( !strcmp( argv[i], "--remove" ) || !strcmp( argv[i], "-" ) ) { if( ++i >= argc ) { CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [remove]...\n" ); goto error; } if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); do { // log EM_log( CK_LOG_INFO, "requesting REMOVE of shred '%i'..." ); msg.param = atoi( argv[i] ); msg.type = MSG_REMOVE; otf_hton( &msg ); ck_send( dest, (char *)&msg, sizeof(msg) ); } while( ++i < argc ); // log EM_poplog(); } else if( !strcmp( argv[i], "--" ) ) { if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); // log EM_log( CK_LOG_INFO, "requesting REMOVE LAST shred..." ); msg.param = CK_NO_VALUE; msg.type = MSG_REMOVE; otf_hton( &msg ); ck_send( dest, (char *)&msg, sizeof(msg) ); // log EM_poplog(); } else if( !strcmp( argv[i], "--replace" ) || !strcmp( argv[i], "=" ) ) { if( ++i >= argc ) { CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [replace]...\n" ); goto error; } if( i <= 0 ) msg.param = CK_NO_VALUE; else msg.param = atoi( argv[i] ); if( ++i >= argc ) { CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [replace]...\n" ); goto error; } if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); EM_log( CK_LOG_INFO, "requesting REPLACE shred '%i' with '%s'...", msg.param, mini(argv[i]) ); msg.type = MSG_REPLACE; if( !otf_send_file( argv[i], msg, "replace", dest ) ) goto error;Lines 1–500 of 782. Load more
/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_otf.cpp // desc: on-the-fly programming utilities // // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) // date: Autumn 2004 //----------------------------------------------------------------------------- #include "chuck_otf.h" #include "chuck_compile.h" #include "chuck_errmsg.h" #include "util_math.h" #include "util_thread.h" #include "util_string.h" #include "util_platforms.h" #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <signal.h> #include <time.h> #ifndef __PLATFORM_WIN32__ #include <unistd.h> #else // 2022 QTSIN #include <winsock2.h> #include <ws2tcpip.h> #include <windows.h> #endif using namespace std; // log level t_CKUINT g_otf_log = CK_LOG_INFO; //----------------------------------------------------------------------------- // name: otf_hton( ) // desc: ... //----------------------------------------------------------------------------- void otf_hton( Net_Msg * msg ) { msg->header = htonl( msg->header ); msg->type = htonl( msg->type ); msg->param = htonl( msg->param ); msg->param2 = htonl( msg->param2 ); msg->param3 = htonl( msg->param3 ); msg->length = htonl( msg->length ); } //----------------------------------------------------------------------------- // name: otf_ntoh( ) // desc: ... //----------------------------------------------------------------------------- void otf_ntoh( Net_Msg * msg ) { msg->header = ntohl( msg->header ); msg->type = ntohl( msg->type ); msg->param = ntohl( msg->param ); msg->param2 = ntohl( msg->param2 ); msg->param3 = ntohl( msg->param3 ); msg->length = ntohl( msg->length ); } //----------------------------------------------------------------------------- // name: recv_file() // desc: ... //----------------------------------------------------------------------------- FILE * recv_file( const Net_Msg & msg, ck_socket sock ) { Net_Msg buf; // what is left // t_CKUINT left = msg.param2; // make a temp file FILE * fd = ck_tmpfile(); // check if successful if( !fd ) { EM_error2( 0, "OTF nable to create temp file, skipping..." ); return NULL; } do { // msg if( !ck_recv( sock, (char *)&buf, sizeof(buf) ) ) goto error; otf_ntoh( &buf ); // write fwrite( buf.buffer, sizeof(char), buf.length, fd ); }while( buf.param2 > 0 ); // check for error if( buf.param2 == NET_ERROR ) { // this was a problem EM_log( CK_LOG_INFO, "(via otf): received error flag, dropping..." ); // done goto error; } return fd; error: fclose( fd ); fd = NULL; return NULL; } //----------------------------------------------------------------------------- // name: otf_process_msg() // desc: ... //----------------------------------------------------------------------------- t_CKUINT otf_process_msg( Chuck_VM * vm, Chuck_Compiler * compiler, Net_Msg * msg, t_CKBOOL immediate, void * data ) { Chuck_Msg * cmd = new Chuck_Msg; Chuck_VM_Code * code = NULL; FILE * fd = NULL; t_CKUINT ret = 0; // CK_FPRINTF_STDERR( "UDP message recv...\n" ); if( msg->type == MSG_REPLACE || msg->type == MSG_ADD ) { string filename; vector<string> args; // parse out command line arguments if( !extract_args( msg->buffer, filename, args ) ) { // error CK_FPRINTF_STDERR( "[chuck]: malformed filename with argument list...\n" ); CK_FPRINTF_STDERR( " --> '%s'", msg->buffer ); SAFE_DELETE(cmd); goto cleanup; } // copy de-escaped filename strcpy( msg->buffer, filename.c_str() ); // copy args if needed if( args.size() > 0 ) { cmd->args = new vector<string>; *(cmd->args) = args; } // see if entire file is on the way if( msg->param2 && msg->param2 != NET_ERROR ) { fd = recv_file( *msg, (ck_socket)data ); if( !fd ) { CK_FPRINTF_STDERR( "[chuck]: incoming source transfer '%s' failed...\n", mini(msg->buffer) ); SAFE_DELETE(cmd); goto cleanup; } } // construct full path to be associated with the file so me.sourceDir() works // (added 1.3.5.2) std::string full_path = get_full_path( msg->buffer ); // special FILE descriptor mode; set autoClose to true compiler->set_file2parse( fd, TRUE ); // parse, type-check, and emit if( !compiler->go( msg->buffer, full_path ) ) { SAFE_DELETE(cmd); goto cleanup; } // get the code code = compiler->output(); // name it code->name += string(msg->buffer); // set the flags for the command cmd->type = msg->type; cmd->code = code; if( msg->type == MSG_REPLACE ) cmd->param = msg->param; } else if( msg->type == MSG_STATUS || msg->type == MSG_REMOVE || msg->type == MSG_REMOVEALL || msg->type == MSG_EXIT || msg->type == MSG_TIME || msg->type == MSG_RESET_ID || msg->type == MSG_CLEARVM ) { cmd->type = msg->type; cmd->param = msg->param; } else if( msg->type == MSG_ABORT ) { // halt and clear current shred vm->abort_current_shred(); // short circuit ret = 1; SAFE_DELETE(cmd); goto cleanup; } else { CK_FPRINTF_STDERR( "[chuck]: unrecognized incoming command from network: '%li'\n", cmd->type ); SAFE_DELETE(cmd); goto cleanup; } // immediate if( immediate ) ret = vm->process_msg( cmd ); else { // queue message vm->queue_msg( cmd, 1 ); // return code ret = 1; } cleanup: // close file handle if( fd ) fclose( fd ); return ret; } //----------------------------------------------------------------------------- // name: otf_send_file() // desc: ... //----------------------------------------------------------------------------- t_CKINT otf_send_file( const char * fname, Net_Msg & msg, const char * op, ck_socket dest ) { FILE * fd = NULL; struct stat fs; string filename; vector<string> args; string buf; // parse out command line arguments if( !extract_args( fname, filename, args ) ) { // error CK_FPRINTF_STDERR( "[chuck]: malformed filename + argument list...\n" ); CK_FPRINTF_STDERR( " --> '%s'", fname ); return FALSE; } // filename and any args strcpy( msg.buffer, fname ); // test it buf = filename; fd = ck_openFileAutoExt( buf, ".ck" ); if( !fd ) { CK_FPRINTF_STDERR( "[chuck]: cannot open file '%s' for [%s]...\n", filename.c_str(), op ); return FALSE; } if( !chuck_parse( filename ) ) { CK_FPRINTF_STDERR( "[chuck]: skipping file '%s' for [%s]...\n", filename.c_str(), op ); fclose( fd ); return FALSE; } // stat it memset( &fs, 0, sizeof(fs) ); stat( buf.c_str(), &fs ); fseek( fd, 0, SEEK_SET ); // log EM_log( CK_LOG_INFO, "sending TCP file %s, size=%d", filename.c_str(), (t_CKUINT)fs.st_size ); EM_pushlog(); // send the first packet msg.param2 = (t_CKUINT)fs.st_size; msg.length = 0; otf_hton( &msg ); // go ck_send( dest, (char *)&msg, sizeof(msg) ); // send the whole thing t_CKUINT left = (t_CKUINT)fs.st_size; while( left ) { // log EM_log( CK_LOG_FINER, "%03d bytes left ... ", left ); // amount to send msg.length = left > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : left; // read msg.param3 = fread( msg.buffer, sizeof(char), msg.length, fd ); // check for error if( !msg.param3 ) { // error encountered CK_FPRINTF_STDERR( "[chuck]: error while reading '%s'...\n", filename.c_str() ); // mark done left = 0; // error flag msg.param2 = NET_ERROR; } else { // amount left left -= msg.param3; // what's left msg.param2 = left; } // log EM_log( CK_LOG_FINER, "sending buffer %03d length %03d...", msg.param3, msg.length ); // send it otf_hton( &msg ); ck_send( dest, (char *)&msg, sizeof(msg) ); } // pop log EM_poplog(); // close fclose( fd ); return TRUE; } //----------------------------------------------------------------------------- // name: otf_send_connect() // desc: ... //----------------------------------------------------------------------------- ck_socket otf_send_connect( const char * host, t_CKINT port ) { // log EM_log( CK_LOG_INFO, "otf connect: %s:%i", host, port ); ck_socket sock = ck_tcp_create( 0 ); if( !sock ) { CK_FPRINTF_STDERR( "[chuck]: cannot open socket to send command...\n" ); return NULL; } if( strcmp( host, "127.0.0.1" ) ) EM_log( g_otf_log, "connecting to %s on port %i via TCP...", host, port ); if( !ck_connect( sock, host, (int)port ) ) { CK_FPRINTF_STDERR( "cannot open TCP socket on %s:%i...\n", host, port ); ck_close( sock ); return NULL; } ck_send_timeout( sock, 0, 2000000 ); return sock; } //----------------------------------------------------------------------------- // name: otf_send_cmd() // desc: ... //----------------------------------------------------------------------------- t_CKINT otf_send_cmd( t_CKINT argc, const char ** argv, t_CKINT & i, const char * host, t_CKINT port, t_CKINT * is_otf ) { Net_Msg msg; // REFACTOR-2017 TODO: wat is global sigpipe mode // g_sigpipe_mode = 1; int tasks_total = 0, tasks_done = 0; ck_socket dest = NULL; if( is_otf ) *is_otf = TRUE; // log EM_log( CK_LOG_INFO, "examining otf command '%s'...", argv[i] ); if( !strcmp( argv[i], "--add" ) || !strcmp( argv[i], "+" ) ) { if( ++i >= argc ) { CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [add]...\n" ); goto error; } if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); do { // log EM_log( CK_LOG_INFO, "sending file:args '%s' for ADD...", mini(argv[i]) ); msg.type = MSG_ADD; msg.param = 1; tasks_done += otf_send_file( argv[i], msg, "add", dest ); tasks_total++; } while( ++i < argc ); // log EM_poplog(); if( !tasks_done ) goto error; } else if( !strcmp( argv[i], "--remove" ) || !strcmp( argv[i], "-" ) ) { if( ++i >= argc ) { CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [remove]...\n" ); goto error; } if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); do { // log EM_log( CK_LOG_INFO, "requesting REMOVE of shred '%i'..." ); msg.param = atoi( argv[i] ); msg.type = MSG_REMOVE; otf_hton( &msg ); ck_send( dest, (char *)&msg, sizeof(msg) ); } while( ++i < argc ); // log EM_poplog(); } else if( !strcmp( argv[i], "--" ) ) { if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); // log EM_log( CK_LOG_INFO, "requesting REMOVE LAST shred..." ); msg.param = CK_NO_VALUE; msg.type = MSG_REMOVE; otf_hton( &msg ); ck_send( dest, (char *)&msg, sizeof(msg) ); // log EM_poplog(); } else if( !strcmp( argv[i], "--replace" ) || !strcmp( argv[i], "=" ) ) { if( ++i >= argc ) { CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [replace]...\n" ); goto error; } if( i <= 0 ) msg.param = CK_NO_VALUE; else msg.param = atoi( argv[i] ); if( ++i >= argc ) { CK_FPRINTF_STDERR( "[chuck]: not enough arguments following [replace]...\n" ); goto error; } if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); EM_log( CK_LOG_INFO, "requesting REPLACE shred '%i' with '%s'...", msg.param, mini(argv[i]) ); msg.type = MSG_REPLACE; if( !otf_send_file( argv[i], msg, "replace", dest ) ) goto error;