📄 task.cc
字号:
int n = arg->Length(); for ( int k = 0; k < n; ++k ) { if ( saw_name ) argv[argp++] = strdup( words[k] ); else // Skip over name. saw_name = 1; } } else { if ( saw_name ) argv[argp++] = arg->StringVal(); else // Skip over name. saw_name = 1; } } argv[argp] = 0; if ( attrs->async_flag ) CreateAsyncClient( argv ); else Exec( argv ); for ( argp = first_arg_pos; argp < first_arg_pos + num_args; ++argp ) delete ((char**) argv)[argp]; delete argv; }void ClientTask::CreateAsyncClient( const char** argv ) { no_such_program = 0; task_error = 0; sequencer->NewClientStarted(); for ( int argc = 0; argv[argc]; ++argc ) ; (void) CreateEvent( "activate", new Value( argv, argc, COPY_ARRAY ) ); }TaskAttr::TaskAttr( char* arg_ID, char* arg_hostname, Channel* arg_daemon_channel, int arg_async_flag, int arg_ping_flag, int arg_suspend_flag ) { task_var_ID = arg_ID; hostname = arg_hostname; daemon_channel = arg_daemon_channel; async_flag = arg_async_flag; ping_flag = arg_ping_flag; suspend_flag = arg_suspend_flag; }TaskAttr::~TaskAttr() { delete task_var_ID; delete hostname; }Value* CreateTaskBuiltIn::DoCall( const_args_list* args_val ) { // Arguments are: // // var-ID hostname client async ping suspend args... // // where "var-ID" and "hostname" are string values, and // client/async/ping/suspend are boolean flags. const_args_list& args = *args_val; int task_args_start = 7; if ( args.length() <= task_args_start ) { error->Report( "too few arguments given to create_task" ); return error_value(); } char* var_ID = GetString( args[0] ); char* hostname = GetString( args[1] ); // If the following values are changed, be sure to also change // them in CreateTaskBuiltIn::DoSideEffectsCall(). int client_flag = args[2]->IntVal(); int async_flag = args[3]->IntVal(); int ping_flag = args[4]->IntVal(); int suspend_flag = args[5]->IntVal(); Value* input = 0; if ( args[6]->Type() != TYPE_BOOL || args[6]->BoolVal() ) input = new Value( (Value*) args[6], VAL_CONST ); Channel* channel = sequencer->GetHostDaemon( hostname ); attrs = new TaskAttr( var_ID, hostname, channel, async_flag, ping_flag, suspend_flag ); // Collect the arguments to the task. const_args_list task_args; for ( int i = task_args_start; i < args.length(); ++i ) task_args.append( args[i] ); Value* result; if ( client_flag ) result = CreateClient( &task_args ); else { // Shell client. if ( async_flag ) result = CreateAsyncShell( &task_args ); else { char* command = paste( &task_args ); if ( hostname ) result = RemoteSynchronousShell( command, input ); else { char* input_str; if ( ! input || (input->Type() == TYPE_BOOL && ! input->BoolVal()) ) input_str = 0; else input_str = input->StringVal( '\n' ); result = SynchronousShell( command, input_str ); delete input_str; } delete attrs; delete command; } } Unref( input ); return result; }void CreateTaskBuiltIn::DoSideEffectsCall( const_args_list* args_val, int& side_effects_okay ) { // Check for synchronous shell call; we allow those to be // for side-effects only. The corresponding arguments are // numbers 2 (client/shell flag) and 3 (async flag). const_args_list& args = *args_val; if ( args.length() > 3 ) { int client_flag = args[2]->IntVal(); int async_flag = args[3]->IntVal(); if ( ! client_flag && ! async_flag ) side_effects_okay = 1; } Unref( DoCall( args_val ) ); }char* CreateTaskBuiltIn::GetString( const Value* val ) { if ( val->Type() == TYPE_BOOL && ! val->BoolVal() ) // False means "default". return 0; else return val->StringVal(); }Value* CreateTaskBuiltIn::SynchronousShell( const char* command, const char* input ) { FILE* shell = popen_with_input( command, input ); if ( ! shell ) { warn->Report( "could not execute shell command \"", command, "\"" ); return error_value(); } Value* result = GetShellCmdOutput( command, shell, 0 ); int status = pclose_with_input( shell ); if ( status ) { char status_buf[128]; sprintf( status_buf, "0x%x", status >> 8 ); warn->Report( "shell command \"", command, "\" terminated with status = ", status_buf ); } return result; }Value* CreateTaskBuiltIn::RemoteSynchronousShell( const char* command, Value* input ) { int fd = attrs->daemon_channel->WriteFD(); Value* r = create_record(); r->SetField( "command", command ); if ( input ) r->SetField( "input", input ); send_event( fd, "shell", r ); Unref( r ); GlishEvent* e = recv_event( attrs->daemon_channel->ReadFD() ); if ( ! e ) { warn->Report( "remote daemon died" ); return error_value(); } int was_okay = e->value->IntVal(); delete e; if ( ! was_okay ) { warn->Report( "could not execute shell command \"", command, "\" on host ", attrs->hostname ); return error_value(); } Value* result = GetShellCmdOutput( command, 0, 1 ); e = recv_event( attrs->daemon_channel->ReadFD() ); if ( ! e ) { warn->Report( "remote daemon died" ); return error_value(); } int status = e->value->IntVal(); delete e; if ( status ) { char status_buf[128]; sprintf( status_buf, "0x%x", status >> 8 ); warn->Report( "shell command \"", command, "\" on host ", attrs->hostname, " terminated with status = ", status_buf ); } return result; }Value* CreateTaskBuiltIn::GetShellCmdOutput( const char* command, FILE* shell, int is_remote ) {#define MAX_CMD_OUTPUT_LINES 8192 charptr event_values[MAX_CMD_OUTPUT_LINES];#define MAX_SHELL_LINE_LEN 8192 char line_buf[MAX_SHELL_LINE_LEN]; int line_num = 0;#define NEXT_CMD_LINE \ (is_remote ? NextRemoteShellCmdLine( line_buf ) : \ NextLocalShellCmdLine( shell, line_buf )) while ( NEXT_CMD_LINE ) { int len = strlen( line_buf ); // Remove trailing newline. if ( len > 0 && line_buf[len - 1] == '\n' ) line_buf[len - 1] = '\0'; if ( ++line_num >= MAX_CMD_OUTPUT_LINES ) { warn->Report( "too much data generated by shell command \"", command, "\"" ); // throw away the remainder of the input while ( NEXT_CMD_LINE ) ; break; } event_values[line_num - 1] = strdup( line_buf ); } charptr* event_values_copy = new charptr[line_num]; copy_array( event_values, event_values_copy, line_num, charptr ); return new Value( event_values_copy, line_num ); }char* CreateTaskBuiltIn::NextLocalShellCmdLine( FILE* shell, char* line_buf ) { return fgets( line_buf, MAX_SHELL_LINE_LEN, shell ); }char* CreateTaskBuiltIn::NextRemoteShellCmdLine( char* line_buf ) { GlishEvent* e = recv_event( attrs->daemon_channel->ReadFD() ); if ( ! e ) { warn->Report( "remote daemon died" ); return 0; } Value* v = e->value; if ( v->Type() != TYPE_STRING ) { // This is the "done" event, with a boolean true as value. delete e; return 0; } char* next_line = v->StringVal(); strcpy( line_buf, next_line ); delete next_line; delete e; return line_buf; }Value* CreateTaskBuiltIn::CreateAsyncShell( const_args_list* args ) { Task* task = new ShellTask( args, attrs, sequencer ); CheckTaskStatus( task ); return task->AgentRecord(); }Value* CreateTaskBuiltIn::CreateClient( const_args_list* args ) { if ( attrs->async_flag ) { if ( attrs->hostname && strcmp( attrs->hostname, "localhost" ) ) error->Report( "hostname option is incompatible with asynchronous client" ); if ( attrs->suspend_flag ) warn->Report( "suspend option is not supported for asynchronous clients" ); } Task* task = new ClientTask( args, attrs, sequencer ); CheckTaskStatus( task ); return task->AgentRecord(); }void CreateTaskBuiltIn::CheckTaskStatus( Task* task ) { if ( task->NoSuchProgram() ) warn->Report( "no such program, \"", task->Name(), "\"" ); else if ( task->Exec() && task->Exec()->ExecError() ) warn->Report( "could not exec program, \"", task->Name(), "\"" ); }int same_host( Task* t1, Task* t2 ) { const char* t1_host = t1->Host(); const char* t2_host = t2->Host(); if ( ! t1_host ) t1_host = "localhost"; if ( ! t2_host ) t2_host = "localhost"; return ! strcmp( t1_host, t2_host ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -