int DockerAPI::stats(const std::string &container, uint64_t &memUsage, uint64_t &netIn, uint64_t &netOut) { newstats(container, memUsage, netIn, netOut); ArgList args; if ( ! add_docker_arg(args)) return -1; args.AppendArg( "stats" ); args.AppendArg( "--no-stream" ); args.AppendArg( container.c_str() ); MyString displayString; TemporaryPrivSentry sentry(PRIV_ROOT); args.GetArgsStringForLogging( & displayString ); dprintf( D_FULLDEBUG, "Attempting to run: %s\n", displayString.c_str() ); // Read from Docker's combined output and error streams. FILE * dockerResults = my_popen( args, "r", 1 , 0, false); if( dockerResults == NULL ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() ); return -2; } const int statLineSize = 256; char header[statLineSize]; char data[statLineSize]; if( NULL == fgets( header, statLineSize, dockerResults ) ) { my_pclose(dockerResults); return -2; } if( NULL == fgets( data, statLineSize, dockerResults ) ) { my_pclose(dockerResults); return -2; } my_pclose(dockerResults); dprintf(D_FULLDEBUG, "Docker stats data is:\n%s\n", data); // condor stats output looks like: // Name cpu% mem usage/limit mem% net i/o block i/o // container 0.00% 0 B / 0 B 0.00% 0 B / 0 B 0 B / 0 B // char memUsageUnit[2]; char netInUnit[2]; char netOutUnit[2]; double memRaw, netInRaw, netOutRaw; int matches = sscanf(data, "%*s %*g%% %lg %s / %*g %*s %*g%% %lg %s / %lg %s", &memRaw, &memUsageUnit[0], &netInRaw, &netInUnit[0], &netOutRaw, &netOutUnit[0]); if (matches < 6) { return -2; } memUsage = convertUnits(memRaw, memUsageUnit); netIn = convertUnits(netInRaw, netInUnit); netOut = convertUnits(netOutRaw, netOutUnit); dprintf(D_FULLDEBUG, "memUsage is %g (%s), net In is %g (%s), net Out is %g (%s)\n", memRaw, memUsageUnit, netInRaw, netInUnit, netOutRaw, netOutUnit); return 0; }
bool DCShadow::getUserCredential( const char* user, const char* domain, MyString& credential) { ReliSock reli_sock; bool result; // For now, if we have to ensure that the update gets // there, we use a ReliSock (TCP). reli_sock.timeout(20); // years of research... :) if( ! reli_sock.connect(_addr) ) { dprintf( D_ALWAYS, "getUserCredential: Failed to connect to shadow " "(%s)\n", _addr ); return false; } result = startCommand( CREDD_GET_PASSWD, (Sock*)&reli_sock ); if( ! result ) { dprintf( D_FULLDEBUG, "Failed to send CREDD_GET_PASSWD command to shadow\n" ); return false; } // Enable encryption if available. If it's not available, our peer // will close the connection. reli_sock.set_crypto_mode(true); MyString senduser = user; MyString senddomain = domain; MyString recvcredential; if(!reli_sock.code(senduser)) { dprintf( D_FULLDEBUG, "Failed to send user (%s) to shadow\n", senduser.c_str() ); return false; } if(!reli_sock.code(senddomain)) { dprintf( D_FULLDEBUG, "Failed to send domain (%s) to shadow\n", senddomain.c_str() ); return false; } if(!reli_sock.end_of_message()) { dprintf( D_FULLDEBUG, "Failed to send EOM to shadow\n" ); return false; } reli_sock.decode(); if(!reli_sock.code(recvcredential)) { dprintf( D_FULLDEBUG, "Failed to receive credential from shadow\n"); return false; } if(!reli_sock.end_of_message()) { dprintf( D_FULLDEBUG, "Failed to receive EOM from shadow\n"); return false; } credential = recvcredential; return true; }
// // FIXME: We have a lot of boilerplate code in this function and file. // int DockerAPI::version( std::string & version, CondorError & /* err */ ) { ArgList versionArgs; if ( ! add_docker_arg(versionArgs)) return -1; versionArgs.AppendArg( "-v" ); MyString displayString; versionArgs.GetArgsStringForLogging( & displayString ); dprintf( D_FULLDEBUG, "Attempting to run: '%s'.\n", displayString.c_str() ); FILE * dockerResults = my_popen( versionArgs, "r", 1 , 0, false); if( dockerResults == NULL ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() ); return -2; } char buffer[1024]; if( NULL == fgets( buffer, 1024, dockerResults ) ) { if( errno ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), strerror( errno ), errno ); } else { dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() ); } my_pclose( dockerResults ); return -3; } if( NULL != fgets( buffer, 1024, dockerResults ) ) { if( strstr( buffer, "Jansens" ) != NULL ) { dprintf( D_ALWAYS | D_FAILURE, "The DOCKER configuration setting appears to point to OpenBox's docker. If you want to use Docker.IO, please set DOCKER appropriately in your configuration.\n" ); } else { dprintf( D_ALWAYS | D_FAILURE, "Read more than one line (or a very long line) from '%s', which we think means it's not Docker. The (first line of the) trailing text was '%s'.\n", displayString.c_str(), buffer ); } my_pclose( dockerResults ); return -5; } int exitCode = my_pclose( dockerResults ); if( exitCode != 0 ) { dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, buffer ); return -4; } unsigned end = strlen(buffer) - 1; if( buffer[end] == '\n' ) { buffer[end] = '\0'; } version = buffer; return 0; }
// helper functions to test the parsing of config files and/or metaknobs // void testparse(int lineno, MACRO_SET & set, MACRO_EVAL_CONTEXT &ctx, MACRO_SOURCE & source, bool verbose, const char * tag, const char * params, const char * expected) { int ret = Parse_config_string(source, 0, params, set, ctx); const char * hashout = NULL; if (ret < 0) { fprintf(stderr, "Failed %5d: test '%s' local=%s subsys=%s parse error %d\n", lineno, tag, ctx.localname ? ctx.localname : "", ctx.subsys ? ctx.subsys : "", ret); gmstr.clear(); hashout = NULL; } else { dump_macro_set(set, gmstr, "\t"); hashout = gmstr.c_str(); if (gmstr != expected) { fprintf(stderr, "Failed %5d: test '%s' local=%s subsys=%s resulting hashtable does not match expected\n", lineno, tag, ctx.localname ? ctx.localname : "", ctx.subsys ? ctx.subsys : ""); ret = -1; } else if (verbose) { fprintf(stdout, " OK %5d: test '%s' local=%s subsys=%s\n", lineno, tag, ctx.localname ? ctx.localname : "", ctx.subsys ? ctx.subsys : ""); ret = 0; } } if (verbose || ret) { fprintf(ret ? stderr : stdout, "\t---- parse input %d ----\n%s", lineno, params); if (hashout) fprintf(ret ? stderr : stdout, "\t---- resulting hash %d ----\n%s", lineno, hashout); if (ret) fprintf(stderr, "\t---- expected hash %d ----\n%s", lineno, expected); fprintf(ret ? stderr : stdout, "\t---- end %d ----\n\n", lineno); } clear_macro_set(set); }
void x_exit(int ret) { MyString str; str.Format("Critical Error : %d",ret); x_fatal_exit(str.c_str()); }
void CommandCd::exec(VirtualDiskNode* vfs) { if (!vfs) { assert(0); return; } if (m_path.isEmpty()) { MyString pwd = vfs->pwd(); if (!pwd.endWith(_T("\\"))) { pwd += _T("\\"); } _tprintf(_T("%s\n"), pwd.c_str()); return; } if (!isNormalizedPath(m_path)) { m_path = vfs->pathNormalize(m_path); } m_path = m_path.toLower(); if (!m_path.startWith(_T("c:"))) { throw CommandException(_T("系统找不到指定的驱动器\n")); } if (!vfs->isDir(m_path)) { throw CommandException(_T("系统找不到指定的目录\n")); } vfs->chdir(m_path); return; }
void CondorQuery::setDesiredAttrs(char const * const *attrs) { MyString val; ::join_args(attrs,&val); setDesiredAttrs(val.c_str()); }
int run_simple_docker_command(const std::string &command, const std::string &container, CondorError &) { ArgList args; if ( ! add_docker_arg(args)) return -1; args.AppendArg( command ); args.AppendArg( container.c_str() ); MyString displayString; args.GetArgsStringForLogging( & displayString ); dprintf( D_FULLDEBUG, "Attempting to run: %s\n", displayString.c_str() ); // Read from Docker's combined output and error streams. FILE * dockerResults = my_popen( args, "r", 1 , 0, false); if( dockerResults == NULL ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() ); return -2; } // On a success, Docker writes the containerID back out. char buffer[1024]; if( NULL == fgets( buffer, 1024, dockerResults ) ) { if( errno ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), strerror( errno ), errno ); } else { dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() ); } my_pclose( dockerResults ); return -3; } int length = strlen( buffer ); if( length < 1 || strncmp( buffer, container.c_str(), length - 1 ) != 0 ) { dprintf( D_ALWAYS | D_FAILURE, "Docker %s failed, printing first few lines of output.\n", command.c_str() ); dprintf( D_ALWAYS | D_FAILURE, "%s", buffer ); while( NULL != fgets( buffer, 1024, dockerResults ) ) { dprintf( D_ALWAYS | D_FAILURE, "%s", buffer ); } my_pclose( dockerResults ); return -4; } my_pclose( dockerResults ); return 0; }
int DockerAPI::detect( CondorError & err ) { // FIXME: Remove ::version() as a public API and return it from here, // because there's no point in doing this twice. std::string version; if( DockerAPI::version( version, err ) != 0 ) { dprintf( D_ALWAYS | D_FAILURE, "DockerAPI::detect() failed to detect the Docker version; assuming absent.\n" ); return -4; } ArgList infoArgs; if ( ! add_docker_arg(infoArgs)) return -1; infoArgs.AppendArg( "info" ); MyString displayString; infoArgs.GetArgsStringForLogging( & displayString ); dprintf( D_FULLDEBUG, "Attempting to run: '%s'.\n", displayString.c_str() ); FILE * dockerResults = my_popen( infoArgs, "r", 1 , 0, false); if( dockerResults == NULL ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() ); return -2; } // Even if we don't care about the success output, the failure output // can be handy for debugging... char buffer[1024]; std::vector< std::string > output; while( fgets( buffer, 1024, dockerResults ) != NULL ) { unsigned end = strlen(buffer) - 1; if( buffer[end] == '\n' ) { buffer[end] = '\0'; } output.push_back( buffer ); } for( unsigned i = 0; i < output.size(); ++i ) { dprintf( D_FULLDEBUG, "[docker info] %s\n", output[i].c_str() ); } int exitCode = my_pclose( dockerResults ); if( exitCode != 0 ) { dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, output[0].c_str() ); return -3; } return 0; }
extern "C" int outputInfo(const char* format,...) { va_list argptr; va_start( argptr, format ); MyString st; st.FormatV(format,argptr); va_end(argptr); puts(st.c_str()); return 1; }
void CDownload::deleteDownloadDirectory() { // détruit le répertoire de téléchargement MyString dir; dir = getPersistentPath(); dir += ACTIVEGS_DIRECTORY_SEPARATOR; dir += activegsdownloaddir; deleteDirectory(dir.c_str(),1); }
void x_alert(const char* format,...) { MyString theAlert; va_list argptr; va_start( argptr, format ); theAlert.FormatV(format,argptr); va_end(argptr); x_display_alert(0,"ActiveGS Warning",theAlert.c_str()); }
long CDownload::retrieveLocalFile(const MYCHAR* _url,int _order,MyString& _path, MyString& _short) { MyString url = _url; MyString ext(getext(url)); if (!ext.CompareNoCase("zip")) { if (!retrieveZippedFile(url,_order,_path,_short)) { if (!unzipFile(url,url)) { // unzip failed... outputInfo("unzip failed (%s)\n",_url); return 0; } if (!retrieveZippedFile(url,_order,_path,_short)) { outputInfo("could not find zip (%s)\n",_url); return 0; } } } else { _path = url; _short = getfile(url); } FILE* f = fopen(_path.c_str(),"rb"); if (f) { /*int err =*/ fseek(f,0,SEEK_END); long size = ftell(f); fclose(f); return size; } else { outputInfo("could not find file (%s)\n",_url); ::showStatus("Failed to load %s",getfile(_url)); return 0; } }
void CommandDir::listDirRecursive(const MyString& path, VirtualDiskNode* vfs, bool only_dir /*= false*/) { _tprintf(_T(" %s 的目录\n\n"), path.c_str()); listDir(path, vfs, only_dir); DirHandler dir_handler = vfs->openDir(path); for (DirIterator iter = dir_handler.getIterator(); !iter.isDone(); iter.next()) { state s = iter.getItem(); if (s.type == DIR_TYPE && !s.name.startWith(_T("."))) { listDirRecursive(s.path, vfs, only_dir); } } }
void showStatus(const MYCHAR* format,...) { va_list argptr; va_start( argptr, format ); MyString st; st.FormatV(format,argptr); va_end(argptr); // outputInfoInternal(st.c_str()); CEmulator* emu = CEmulator::theEmulator; if (emu) emu->showStatus(st.c_str()); }
MyString CDownload::getPersistentDir(const char* url) { MyString dir; // dir.Format("%s"ACTIVEGS_DIRECTORY_SEPARATOR"%s.%08X",getPersistentPath(),getfilenoext(url),calcCRC(url)); dir = getPersistentPath(); dir += ACTIVEGS_DIRECTORY_SEPARATOR; dir += getfilenoext(url) ; /* MyString urldir; getdir(url,urldir); */ MyString temp; temp.Format(".%08X",calcCRC(url)); dir += temp.c_str(); return dir ; }
int main() { const MyString cs("Ein konstanter String"); MyString s(cs); s.assign(cs); s.append(cs); cout << cs.c_str() << endl; cout << cs.size() << endl; cout << cs.capacity() << endl; cout << boolalpha << cs.empty() << endl; s = cs + cs; cout << (cs == cs) << endl; s = cs; cout << cs << endl; s.at(1) = 'X'; s[2] = 'Y'; // Hallo cout << s << endl; cin.get(); return 0; }
void showProgress(const char* file,int percent) { MyString progress; if (percent>=0) progress.Format("Downloading: %s (%3d%%)",getfile(file),percent); else progress.Format("Downloading: %s (%4dK)",getfile(file),(int)(-percent/1024)); // outputInfoInternal(progress.c_str()); CEmulator* emu = CEmulator::theEmulator; if (emu) emu->showStatus(progress.c_str()); #ifdef DRIVER_IOS extern void x_downloadinginprogress(int); x_downloadinginprogress(percent); #endif }
static void CreateData() { for(int i = 0; i < 3; i++) { ConsonantsRatesSum[i] = CountRateSum(Consonants, ConsonantsNumber, i); VowelsRatesSum[i] = CountRateSum(Vowels, VowelsNumber, i); } for( int i=0; i<N; ++i ) { int type = rand(); Data[i] = GetLetters(type++, 0); for( int j = 0; j < type%size_factor; ++j ) Data[i] += GetLetters(type++, 1); Data[i] += GetLetters(type, 2); } MyString planet = Data[12]; planet[0] = toupper(planet[0]); MyString helloworld = Data[0]; helloworld[0] = toupper(helloworld[0]); helloworld += ", "+Data[1]+" "+Data[2]+" "+Data[3]+" "+Data[4]+" "+Data[5]; if ( !silent ) printf("Message from planet '%s': %s!\nAnalyzing whole text...\n", planet.c_str(), helloworld.c_str()); }
void Sinful::parseV1String() { std::vector< SourceRoute > v; if(! getSourceRoutes( v, & m_host, & m_port ) ) { m_valid = false; return; } // // To convert a list of source routes back into an original Sinful's // data structures, do the following: // // (1) Extract the spid from each route; they must all be the same. // Set the spid. // (2) Extract the alias from each route; they must all be the same. // Set the alias. // (3) Extract the private network name from each route; they must // all be the same. Set the private network name. // (4) Check all routes for ccbid. Each route with a ccbid goes // into the ccb contact list. // (5) All routes without a ccbid must be "Internet" addresses or // private network addresses. The former go into addrs (and // host is set to addrs[0]). Ignore all of the latter that // have an address in addrs (because those came from CCB). The // remaining address must be the private network address. // // Determine the shared port ID, if any. If any route has a // shared port ID, all must have one, and it must be the same. const std::string & sharedPortID = v[0].getSharedPortID(); if(! sharedPortID.empty() ) { setSharedPortID( v[0].getSharedPortID().c_str() ); for( unsigned i = 0; i < v.size(); ++i ) { if( v[i].getSharedPortID() != sharedPortID ) { m_valid = false; return; } } } // Determine the alias, if any. If more than one route has an alias, // each alias must be the same. std::string alias; for( unsigned i = 0; i < v.size(); ++i ) { if(! v[i].getAlias().empty()) { if(! alias.empty()) { if( alias != v[i].getAlias() ) { m_valid = false; return; } } else { alias = v[i].getAlias(); } } } if(! alias.empty() ) { setAlias( alias.c_str() ); } // Determine the private network name, if any. If more than one route // has a private network name, each private network name must be the same. std::string privateNetworkName; for( unsigned i = 0; i < v.size(); ++i ) { if( v[i].getNetworkName() != PUBLIC_NETWORK_NAME ) { if(! privateNetworkName.empty()) { if( v[i].getNetworkName() != privateNetworkName ) { m_valid = false; return; } } else { privateNetworkName = v[i].getNetworkName(); } } } if(! privateNetworkName.empty() ) { setPrivateNetworkName( privateNetworkName.c_str() ); } // // Determine the CCB contact string, if any. // // Each group of routes which shared a broker index must be converted // back into the single original Sinful from which it sprang; that // Sinful can than be added to the ccbList with its CCB ID. // StringList ccbList; std::map< unsigned, std::string > brokerCCBIDs; std::map< unsigned, std::vector< SourceRoute > > brokers; for( unsigned i = 0; i < v.size(); ++i ) { if( v[i].getCCBID().empty() ) { continue; } SourceRoute sr = v[i]; sr.setSharedPortID( sr.getCCBSharedPortID() ); sr.setCCBSharedPortID( "" ); sr.setCCBID( "" ); unsigned brokerIndex = sr.getBrokerIndex(); brokers[brokerIndex].push_back( sr ); brokerCCBIDs[brokerIndex] = v[i].getCCBID(); dprintf( D_ALWAYS, "broker %u = %s\n", brokerIndex, sr.serialize().c_str() ); } for( unsigned i = 0; i < brokers.size(); ++i ) { std::string brokerV1String = "{"; brokerV1String += brokers[i][0].serialize(); for( unsigned j = 0; j < brokers[i].size(); ++j ) { brokerV1String += ", "; brokerV1String += brokers[i][j].serialize(); } brokerV1String += "}"; Sinful s( brokerV1String.c_str() ); std::string ccbAddress = s.getCCBAddressString(); CCBID ccbID; if(! CCBServer::CCBIDFromString( ccbID, brokerCCBIDs[i].c_str() )) { m_valid = false; return; } MyString ccbContactString; CCBServer::CCBIDToContactString( ccbAddress.c_str(), ccbID, ccbContactString ); ccbList.append( ccbContactString.c_str() ); } if(! ccbList.isEmpty() ) { char * ccbID = ccbList.print_to_delimed_string( " " ); ASSERT( ccbID != NULL ); setCCBContact( ccbID ); free( ccbID ); } // Determine the set of public addresses. for( unsigned i = 0; i < v.size(); ++i ) { if( v[i].getProtocol() == CP_PRIMARY ) { continue; } if(! v[i].getCCBID().empty()) { continue; } if( v[i].getNetworkName() == PUBLIC_NETWORK_NAME ) { addAddrToAddrs( v[i].getSockAddr() ); } } // Determine the private network address, if any. for( unsigned i = 0; i < v.size(); ++i ) { if(! v[i].getCCBID().empty()) { continue; } if( v[i].getNetworkName() == PUBLIC_NETWORK_NAME ) { continue; } // A route with a public address may have a private network name // as a result of bypassing CCB. Those addresses are not private // addresses, so ignore them. condor_sockaddr sa = v[i].getSockAddr(); if( std::find( addrs.begin(), addrs.end(), sa ) != addrs.end() ) { continue; } // There can be only one private address. if( getPrivateAddr() != NULL ) { m_valid = false; return; } // setPrivateAddr( Sinful::privateAddressString( v[i].getSockAddr(), getSharedPortID() ).c_str() ); Sinful p( v[i].getSockAddr().to_ip_and_port_string().c_str() ); p.setSharedPortID( getSharedPortID() ); setPrivateAddr( p.getSinful() ); } // Set noUDP if any route sets it. for( unsigned i = 0; i < v.size(); ++i ) { if( v[i].getNoUDP() ) { setNoUDP( true ); break; } } m_valid = true; }
{ int rval = 0; // if submit foreach data is not already a disk file, turn it into one. bool make_foreach_file = false; if (spill_items) { PRAGMA_REMIND("TODO: only spill foreach data to a file if it is larger than a certain size.") if (o.items.isEmpty()) { o.foreach_mode = foreach_not; } else { make_foreach_file = true; } } else if (o.foreach_mode == foreach_from) { // if it is a file, make sure the path is fully qualified. MyString foreach_fn = o.items_filename; o.items_filename = hash.full_path(foreach_fn.c_str(), false); } // if we are makeing the foreach file, we had to wait until we got the cluster id to do that // so make it now. if (make_foreach_file) { MyString foreach_fn; //PRAGMA_REMIND("tj: REMOVE THIS HACK") if (default_to_factory) { // hack to make the test suite work. foreach_fn.formatstr("condor_submit.%d.%u.items", ClusterId, submit_unique_id); } else { foreach_fn.formatstr("condor_submit.%d.items", ClusterId); } o.items_filename = hash.full_path(foreach_fn.c_str(), false); int fd = safe_open_wrapper_follow(o.items_filename.c_str(), O_WRONLY|_O_BINARY|O_CREAT|O_TRUNC|O_APPEND, 0644);
int Starter::execDCStarter( Stream* s ) { ArgList args; // decide whether we are going to pass a -slot-name argument to the starter // by default we do things the pre 8.1.4 way // we default to -slot-name, but that can be disabled by setting STARTER_LOG_NAME_APPEND = true // otherwise the value of this param determines what we append. bool slot_arg = false; enum { APPEND_NOTHING, APPEND_SLOT, APPEND_CLUSTER, APPEND_JOBID } append = APPEND_SLOT; // by default, single slots machines get no log append and no slot argument. if ( ! resmgr->is_smp()) { slot_arg = false; append = APPEND_NOTHING; } MyString ext; if (param(ext, "STARTER_LOG_NAME_APPEND")) { slot_arg = true; if (MATCH == strcasecmp(ext.c_str(), "Slot")) { append = APPEND_SLOT; } else if (MATCH == strcasecmp(ext.c_str(), "ClusterId") || MATCH == strcasecmp(ext.c_str(), "Cluster")) { append = APPEND_CLUSTER; } else if (MATCH == strcasecmp(ext.c_str(), "JobId")) { append = APPEND_JOBID; } else if (MATCH == strcasecmp(ext.c_str(), "false") || MATCH == strcasecmp(ext.c_str(), "0")) { append = APPEND_NOTHING; } else if (MATCH == strcasecmp(ext.c_str(), "true") || MATCH == strcasecmp(ext.c_str(), "1")) { append = APPEND_SLOT; slot_arg = false; } } char* hostname = s_claim->client()->host(); args.AppendArg("condor_starter"); args.AppendArg("-f"); // Note: the "-a" option is a daemon core option, so it // must come first on the command line. if (append != APPEND_NOTHING) { args.AppendArg("-a"); switch (append) { case APPEND_CLUSTER: args.AppendArg(s_claim->cluster()); break; case APPEND_JOBID: { MyString jobid; jobid.formatstr("%d.%d", s_claim->cluster(), s_claim->proc()); args.AppendArg(jobid.c_str()); } break; default: case APPEND_SLOT: args.AppendArg(s_claim->rip()->r_id_str); break; } } if (slot_arg) { args.AppendArg("-slot-name"); args.AppendArg(s_claim->rip()->r_id_str); } args.AppendArg(hostname); execDCStarter( args, NULL, NULL, s ); return s_pid; }
int CommandCopy::copyFile(MyString src, MyString dst, VirtualDiskNode* vfs) { HANDLE src_file = CreateFile(src.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (src_file == INVALID_HANDLE_VALUE) { throw CommandException(_T("系统找不到指定的文件\n")); } DWORD file_size = GetFileSize(src_file, nullptr); //CHAR *src_buf = new CHAR[file_size]; DelegateMem<char> src_buf(new char[file_size]); DWORD read_bytes = 0; if (!ReadFile(src_file, src_buf, file_size, &read_bytes, nullptr) || file_size != read_bytes) { //delete[] src_buf; CloseHandle(src_file); throw CommandException(src + _T("文件读取失败\n")); } FileHandler dst_file(nullptr); if (vfs->isFile(dst)) { _tprintf(_T("覆盖文件%s,是否确认<Y/N>?"), basename(dst).c_str()); TCHAR confirm = 0; _tscanf_s(_T("%c%*c"), &confirm, sizeof(confirm)); if (confirm != 'y' && confirm != 'Y') { return 0; } dst_file = vfs->openFile(dst); if (!dst_file.isValid()) { //delete[] src_buf; CloseHandle(src_file); throw CommandException(_T("无法打开/创建目标文件\n")); } } else { dst_file = vfs->createFile(dst); if (!dst_file.isValid()) { CloseHandle(src_file); throw CommandException(_T("无法打开/创建目标文件\n")); } } // TODO : 文件写入 dst_file.write(src_buf, file_size); //delete[] src_file; CloseHandle(src_file); return 0; }
int run_simple_docker_command(const std::string &command, const std::string &container, int timeout, CondorError &, bool ignore_output) { ArgList args; if ( ! add_docker_arg(args)) return -1; args.AppendArg( command ); args.AppendArg( container.c_str() ); MyString displayString; args.GetArgsStringForLogging( & displayString ); dprintf( D_FULLDEBUG, "Attempting to run: %s\n", displayString.c_str() ); #if 1 MyPopenTimer pgm; if (pgm.start_program( args, true, NULL, false ) < 0) { dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() ); return -2; } if ( ! pgm.wait_and_close(timeout) || pgm.output_size() <= 0) { int error = pgm.error_code(); if( error ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), pgm.error_str(), error ); if (pgm.was_timeout()) { dprintf( D_ALWAYS | D_FAILURE, "Declaring a hung docker\n"); return DockerAPI::docker_hung; } } else { dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() ); } return -3; } // On a success, Docker writes the containerID back out. MyString line; line.readLine(pgm.output()); line.chomp(); line.trim(); if (!ignore_output && line != container.c_str()) { // Didn't get back the result I expected, report the error and check to see if docker is hung. dprintf( D_ALWAYS | D_FAILURE, "Docker %s failed, printing first few lines of output.\n", command.c_str()); for (int ii = 0; ii < 10; ++ii) { if ( ! line.readLine(pgm.output(), false)) break; dprintf( D_ALWAYS | D_FAILURE, "%s\n", line.c_str() ); } return -4; } #else // Read from Docker's combined output and error streams. FILE * dockerResults = my_popen( args, "r", 1 , 0, false); if( dockerResults == NULL ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() ); return -2; } // On a success, Docker writes the containerID back out. char buffer[1024]; if( NULL == fgets( buffer, 1024, dockerResults ) ) { if( errno ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), strerror( errno ), errno ); } else { dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() ); } my_pclose( dockerResults ); return -3; } size_t length = strlen( buffer ); if (!ignore_output) { if( length < 1 || strncmp( buffer, container.c_str(), length - 1 ) != 0 ) { dprintf( D_ALWAYS | D_FAILURE, "Docker %s failed, printing first few lines of output.\n", command.c_str() ); dprintf( D_ALWAYS | D_FAILURE, "%s", buffer ); while( NULL != fgets( buffer, 1024, dockerResults ) ) { dprintf( D_ALWAYS | D_FAILURE, "%s", buffer ); } my_pclose( dockerResults ); return -4; } } my_pclose( dockerResults ); #endif return 0; }
int DockerAPI::inspect( const std::string & containerID, ClassAd * dockerAd, CondorError & /* err */ ) { if( dockerAd == NULL ) { dprintf( D_ALWAYS | D_FAILURE, "dockerAd is NULL.\n" ); return -2; } ArgList inspectArgs; if ( ! add_docker_arg(inspectArgs)) return -1; inspectArgs.AppendArg( "inspect" ); inspectArgs.AppendArg( "--format" ); StringList formatElements( "ContainerId=\"{{.Id}}\" " "Pid={{.State.Pid}} " "Name=\"{{.Name}}\" " "Running={{.State.Running}} " "ExitCode={{.State.ExitCode}} " "StartedAt=\"{{.State.StartedAt}}\" " "FinishedAt=\"{{.State.FinishedAt}}\" " "DockerError=\"{{.State.Error}}\" " "OOMKilled=\"{{.State.OOMKilled}}\" " ); char * formatArg = formatElements.print_to_delimed_string( "\n" ); inspectArgs.AppendArg( formatArg ); free( formatArg ); inspectArgs.AppendArg( containerID ); MyString displayString; inspectArgs.GetArgsStringForLogging( & displayString ); dprintf( D_FULLDEBUG, "Attempting to run: %s\n", displayString.c_str() ); #if 1 MyPopenTimer pgm; if (pgm.start_program(inspectArgs, true, NULL, false) < 0) { dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() ); return -6; } MyStringSource * src = NULL; if (pgm.wait_and_close(default_timeout)) { src = &pgm.output(); } int expected_rows = formatElements.number(); dprintf( D_FULLDEBUG, "exit_status=%d, error=%d, %d bytes. expecting %d lines\n", pgm.exit_status(), pgm.error_code(), pgm.output_size(), expected_rows ); // If the output isn't exactly formatElements.number() lines long, // something has gone wrong and we'll at least be able to print out // the error message(s). std::vector<std::string> correctOutput(expected_rows); if (src) { MyString line; int i=0; while (line.readLine(*src,false)) { line.chomp(); //dprintf( D_FULLDEBUG, "\t[%2d] %s\n", i, line.c_str() ); if (i >= expected_rows) { if (line.empty()) continue; correctOutput.push_back(line.c_str()); } else { correctOutput[i] = line.c_str(); } std::string::iterator first = std::find(correctOutput[i].begin(), correctOutput[i].end(), '\"'); if (first != correctOutput[i].end()) { std::replace(++first, --correctOutput[i].end(), '\"','\''); } //dprintf( D_FULLDEBUG, "\tfix: %s\n", correctOutput[i].c_str() ); ++i; } } #else FILE * dockerResults = my_popen( inspectArgs, "r", 1 , 0, false); if( dockerResults == NULL ) { dprintf( D_ALWAYS | D_FAILURE, "Unable to run '%s'.\n", displayString.c_str() ); return -6; } // If the output isn't exactly formatElements.number() lines long, // something has gone wrong and we'll at least be able to print out // the error message(s). char buffer[1024]; std::vector<std::string> correctOutput(formatElements.number()); for( int i = 0; i < formatElements.number(); ++i ) { if( fgets( buffer, 1024, dockerResults ) != NULL ) { correctOutput[i] = buffer; std::string::iterator first = std::find(correctOutput[i].begin(), correctOutput[i].end(), '\"'); if (first != correctOutput[i].end()) { std::replace(++first, -- --correctOutput[i].end(), '\"','\''); } } } my_pclose( dockerResults ); #endif int attrCount = 0; for( int i = 0; i < formatElements.number(); ++i ) { if( correctOutput[i].empty() || dockerAd->Insert( correctOutput[i].c_str() ) == FALSE ) { break; } ++attrCount; } if( attrCount != formatElements.number() ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to create classad from Docker output (%d). Printing up to the first %d (nonblank) lines.\n", attrCount, formatElements.number() ); for( int i = 0; i < formatElements.number() && ! correctOutput[i].empty(); ++i ) { dprintf( D_ALWAYS | D_FAILURE, "%s", correctOutput[i].c_str() ); } return -4; } dprintf( D_FULLDEBUG, "docker inspect printed:\n" ); for( int i = 0; i < formatElements.number() && ! correctOutput[i].empty(); ++i ) { dprintf( D_FULLDEBUG, "\t%s\n", correctOutput[i].c_str() ); } return 0; }
std::vector<condor_sockaddr> resolve_hostname_raw(const MyString& hostname) { // // For now, we can just document that you need the Punycoded DSN name. // If somebody complains about that, we can revisit this. (If we // assume/require UTF-8 (int the config file), we can still readily // distinguish Sinfuls, since ':' and '?' won't be used by the UTF-8 // IDNs.) // std::vector<condor_sockaddr> ret; for( int i = 0; i < hostname.length(); ++i ) { if( isalnum( hostname[i] ) || hostname[i] == '-' ) { continue; } if( hostname[i] == '.' && i + 1 < hostname.length() && hostname[i+1] != '.' ) { continue; } dprintf( D_HOSTNAME, "resolve_hostname_raw(): argument '%s' is not a valid DNS name, returning no addresses.\n", hostname.c_str() ); return ret; } addrinfo_iterator ai; int res = ipv6_getaddrinfo(hostname.Value(), NULL, ai); if (res) { dprintf(D_HOSTNAME, "ipv6_getaddrinfo() could not look up %s: %s (%d)\n", hostname.Value(), gai_strerror(res), res); return ret; } // To eliminate duplicate address, here we use std::set. // we also want to maintain the order given by getaddrinfo. std::set<condor_sockaddr> s; while (addrinfo* info = ai.next()) { condor_sockaddr addr(info->ai_addr); if (s.find(addr) == s.end()) { ret.push_back(addr); s.insert(addr); } } return ret; }
int DockerProc::StartJob() { std::string imageID; if( ! JobAd->LookupString( ATTR_DOCKER_IMAGE, imageID ) ) { dprintf( D_ALWAYS | D_FAILURE, "%s not defined in job ad, unable to start job.\n", ATTR_DOCKER_IMAGE ); return FALSE; } std::string command; JobAd->LookupString( ATTR_JOB_CMD, command ); dprintf( D_FULLDEBUG, "%s: '%s'\n", ATTR_JOB_CMD, command.c_str() ); std::string sandboxPath = Starter->jic->jobRemoteIWD(); // // This code is deliberately wrong, probably for backwards-compability. // (See the code in JICShadow::beginFileTransfer(), which assumes that // we transferred the executable if ATTR_TRANSFER_EXECUTABLE is unset.) // Rather than risk breaking anything by fixing condor_submit (which // does not set ATTR_TRANSFER_EXECUTABLE unless it's false) -- and // introducing a version dependency -- assume the executable was // transferred unless it was explicitly noted otherwise. // bool transferExecutable = true; JobAd->LookupBool( ATTR_TRANSFER_EXECUTABLE, transferExecutable ); if( transferExecutable ) { command = sandboxPath + "/" + command; } ArgList args; args.SetArgV1SyntaxToCurrentPlatform(); MyString argsError; if( ! args.AppendArgsFromClassAd( JobAd, & argsError ) ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to read job arguments from job ad: '%s'.\n", argsError.c_str() ); return FALSE; } Env job_env; MyString env_errors; if( !Starter->GetJobEnv(JobAd,&job_env,&env_errors) ) { dprintf( D_ALWAYS, "Aborting DockerProc::StartJob: %s\n", env_errors.Value()); return 0; } // The GlobalJobID is unsuitable by virtue its octothorpes. This // construction is informative, but could be made even less likely // to collide if it had a timestamp. formatstr( containerName, "HTCJob%d_%d_%s_PID%d", Starter->jic->jobCluster(), Starter->jic->jobProc(), Starter->getMySlotName().c_str(), // note: this can be "" for single slot machines. getpid() ); // // Do I/O redirection (includes streaming). // int childFDs[3] = { -2, -2, -2 }; { TemporaryPrivSentry sentry(PRIV_USER); // getStdFile() returns -1 on error. if( -1 == (childFDs[0] = openStdFile( SFT_IN, NULL, true, "Input file" )) ) { dprintf( D_ALWAYS | D_FAILURE, "DockerProc::StartJob(): failed to open stdin.\n" ); return FALSE; } if( -1 == (childFDs[1] = openStdFile( SFT_OUT, NULL, true, "Output file" )) ) { dprintf( D_ALWAYS | D_FAILURE, "DockerProc::StartJob(): failed to open stdout.\n" ); daemonCore->Close_FD( childFDs[0] ); return FALSE; } if( -1 == (childFDs[2] = openStdFile( SFT_ERR, NULL, true, "Error file" )) ) { dprintf( D_ALWAYS | D_FAILURE, "DockerProc::StartJob(): failed to open stderr.\n" ); daemonCore->Close_FD( childFDs[0] ); daemonCore->Close_FD( childFDs[1] ); return FALSE; } } // Ulog the execute event Starter->jic->notifyJobPreSpawn(); CondorError err; // DockerAPI::run() returns a PID from daemonCore->Create_Process(), which // makes it suitable for passing up into VanillaProc. This combination // will trigger the reaper(s) when the container terminates. ClassAd *machineAd = Starter->jic->machClassAd(); std::list<std::string> extras; buildExtraVolumes(extras); int rv = DockerAPI::run( *machineAd, containerName, imageID, command, args, job_env, sandboxPath, extras, JobPid, childFDs, err ); if( rv < 0 ) { dprintf( D_ALWAYS | D_FAILURE, "DockerAPI::run( %s, %s, ... ) failed with return value %d\n", imageID.c_str(), command.c_str(), rv ); return FALSE; } dprintf( D_FULLDEBUG, "DockerAPI::run() returned pid %d\n", JobPid ); // TODO: Start a timer to poll for job usage updates. ++num_pids; // Used by OsProc::PublishUpdateAd(). return TRUE; }
// // FIXME: We have a lot of boilerplate code in this function and file. // int DockerAPI::version( std::string & version, CondorError & /* err */ ) { ArgList versionArgs; if ( ! add_docker_arg(versionArgs)) return -1; versionArgs.AppendArg( "-v" ); MyString displayString; versionArgs.GetArgsStringForLogging( & displayString ); dprintf( D_FULLDEBUG, "Attempting to run: '%s'.\n", displayString.c_str() ); #if 1 MyPopenTimer pgm; if (pgm.start_program(versionArgs, true, NULL, false) < 0) { // treat 'file not found' as not really error int d_level = (pgm.error_code() == ENOENT) ? D_FULLDEBUG : (D_ALWAYS | D_FAILURE); dprintf(d_level, "Failed to run '%s' errno=%d %s.\n", displayString.c_str(), pgm.error_code(), pgm.error_str() ); return -2; } int exitCode; if ( ! pgm.wait_for_exit(default_timeout, &exitCode)) { pgm.close_program(1); dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), pgm.error_str(), pgm.error_code() ); return -3; } if (pgm.output_size() <= 0) { dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() ); return -3; } MyStringSource * src = &pgm.output(); MyString line; if (line.readLine(*src, false)) { line.chomp(); bool jansens = strstr( line.c_str(), "Jansens" ) != NULL; bool bad_size = ! src->isEof() || line.size() > 1024 || line.size() < (int)sizeof("Docker version "); if (bad_size && ! jansens) { // check second line of output for the word Jansens also. MyString tmp; tmp.readLine(*src, false); jansens = strstr( tmp.c_str(), "Jansens" ) != NULL; } if (jansens) { dprintf( D_ALWAYS | D_FAILURE, "The DOCKER configuration setting appears to point to OpenBox's docker. If you want to use Docker.IO, please set DOCKER appropriately in your configuration.\n" ); return -5; } else if (bad_size) { dprintf( D_ALWAYS | D_FAILURE, "Read more than one line (or a very long line) from '%s', which we think means it's not Docker. The (first line of the) trailing text was '%s'.\n", displayString.c_str(), line.c_str() ); return -5; } } if( exitCode != 0 ) { dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, line.c_str() ); return -4; } version = line.c_str(); #else FILE * dockerResults = my_popen( versionArgs, "r", 1 , 0, false); if( dockerResults == NULL ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() ); return -2; } char buffer[1024]; if( NULL == fgets( buffer, 1024, dockerResults ) ) { if( errno ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), strerror( errno ), errno ); } else { dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() ); } my_pclose( dockerResults ); return -3; } if( NULL != fgets( buffer, 1024, dockerResults ) ) { if( strstr( buffer, "Jansens" ) != NULL ) { dprintf( D_ALWAYS | D_FAILURE, "The DOCKER configuration setting appears to point to OpenBox's docker. If you want to use Docker.IO, please set DOCKER appropriately in your configuration.\n" ); } else { dprintf( D_ALWAYS | D_FAILURE, "Read more than one line (or a very long line) from '%s', which we think means it's not Docker. The (first line of the) trailing text was '%s'.\n", displayString.c_str(), buffer ); } my_pclose( dockerResults ); return -5; } int exitCode = my_pclose( dockerResults ); if( exitCode != 0 ) { dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, buffer ); return -4; } size_t end = strlen(buffer); if (end > 0 && buffer[end-1] == '\n') { buffer[end-1] = '\0'; } version = buffer; #endif sscanf(version.c_str(), "Docker version %d.%d", &DockerAPI::majorVersion, &DockerAPI::minorVersion); return 0; }
void x_async_refresh(CGContextRef myContext,CGRect myBoundingBox) { #ifdef ENABLEQD CEmulatorMac* pEmu = (CEmulatorMac*)CEmulator::theEmulator; if (!pEmu) return ; #endif #ifndef DRIVER_IOS x_vbl_count++; #endif addFrameRate(0); CHANGE_BORDER(1,0xFF); // OG if (macUsingCoreGraphics) { if(r_sim65816.is_emulator_offscreen_available() && g_kimage_offscreen.dev_handle) { /* void addConsoleWindow(Kimage* _dst); addConsoleWindow(&g_kimage_offscreen); */ CGContextSaveGState(myContext); #ifndef DRIVER_IOS // CGContextTranslateCTM(myContext,0.0, X_A2_WINDOW_HEIGHT); CGContextTranslateCTM(myContext,0.0, myBoundingBox.size.height); CGContextScaleCTM(myContext,1.0,-1.0); #endif CGImageRef myImage = CGBitmapContextCreateImage((CGContextRef)g_kimage_offscreen.dev_handle); CGContextDrawImage(myContext, myBoundingBox, myImage);// 6 #ifndef VIDEO_SINGLEVLINE if (r_sim65816.get_video_fx() == VIDEOFX_CRT) { CGContextSetRGBFillColor(myContext,0,0,0,0.5); for(int h=0;h<g_kimage_offscreen.height;h+=2) { CGRect r = CGRectMake(0,h,g_kimage_offscreen.width_act,1); CGContextFillRect(myContext,r); } } #endif CGImageRelease(myImage); CGContextRestoreGState(myContext); #ifndef DRIVER_IOS if (!messageLine.IsEmpty()) { CGContextSaveGState(myContext); CGContextSetTextMatrix(myContext,CGAffineTransformIdentity); CGContextTranslateCTM(myContext,0.0, X_A2_WINDOW_HEIGHT); CGContextScaleCTM(myContext,1.0,-1.0); CGContextSelectFont(myContext, "Courier", 14.0, kCGEncodingMacRoman); CGContextSetTextDrawingMode(myContext, kCGTextFill); CGContextSetRGBFillColor (myContext, 1,1, 1, 1); CGContextSetShouldAntialias(myContext, true); #define SHADOW 4.0 CGFloat myColorValues[] = {0.5, 0.5, 0.5, 1.0}; CGColorSpaceRef myColorSpace = CGColorSpaceCreateDeviceRGB ();// 9 CGColorRef myColor = CGColorCreate (myColorSpace, myColorValues); CGContextSetShadowWithColor(myContext, CGSizeMake(SHADOW, -SHADOW), 4, myColor //CGColorCreateGenericGray(0.5,1.0) ); CGContextShowTextAtPoint(myContext, 20.0, X_A2_WINDOW_HEIGHT-20.0, messageLine.c_str(), messageLine.GetLength()); CGContextRestoreGState(myContext); messageLineVBL--; if (messageLineVBL<0) messageLine.Empty(); else x_refresh_video(); } #endif } else { CGContextSaveGState(myContext); #if defined(DRIVER_IOS) // efface en noir si l'émulateur n'avait pas encore démarré (le cas sur 3GS) CGContextSetRGBFillColor (myContext, 0, 0, 0, 1); #else CGContextSetRGBFillColor (myContext, 0, 0, 1, 1); #endif CGContextFillRect (myContext, CGRectMake (0, 0, X_A2_WINDOW_WIDTH, X_A2_WINDOW_HEIGHT)); CGContextRestoreGState(myContext); } } else { #ifdef ENABLEQD CGrafPtr window_port = pEmu->window_port; Rect src_rect; Rect dest_rect; SetRect(&src_rect,0,0,704,462); SetRect(&dest_rect,0,0,704,462); if (pixmap_backbuffer) CopyBits( (BitMap *)(*pixmap_backbuffer), GetPortBitMapForCopyBits(window_port), &src_rect, &dest_rect, srcCopy, NULL); #endif } CHANGE_BORDER(1,0); if (r_sim65816.is_emulator_offscreen_available() && g_driver.x_handle_state_on_paint) g_driver.x_handle_state_on_paint(myBoundingBox.size.width,myBoundingBox.size.height); }
int DockerAPI::detect( CondorError & err ) { // FIXME: Remove ::version() as a public API and return it from here, // because there's no point in doing this twice. std::string version; int rval = DockerAPI::version( version, err ); if( rval != 0 ) { dprintf(D_ALWAYS, "DockerAPI::detect() failed to detect the Docker version; assuming absent.\n" ); return -4; } ArgList infoArgs; if ( ! add_docker_arg(infoArgs)) return -1; infoArgs.AppendArg( "info" ); MyString displayString; infoArgs.GetArgsStringForLogging( & displayString ); dprintf( D_FULLDEBUG, "Attempting to run: '%s'.\n", displayString.c_str() ); #if 1 MyPopenTimer pgm; if (pgm.start_program(infoArgs, true, NULL, false) < 0) { dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() ); return -2; } int exitCode; if ( ! pgm.wait_for_exit(default_timeout, &exitCode) || exitCode != 0) { pgm.close_program(1); MyString line; line.readLine(pgm.output(), false); line.chomp(); dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, line.c_str()); return -3; } if (IsFulldebug(D_ALWAYS)) { MyString line; do { line.readLine(pgm.output(), false); line.chomp(); dprintf( D_FULLDEBUG, "[docker info] %s\n", line.c_str() ); } while (line.readLine(pgm.output(), false)); } #else FILE * dockerResults = my_popen( infoArgs, "r", 1 , 0, false); if( dockerResults == NULL ) { dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() ); return -2; } // Even if we don't care about the success output, the failure output // can be handy for debugging... char buffer[1024]; std::vector< std::string > output; while( fgets( buffer, 1024, dockerResults ) != NULL ) { size_t end = strlen(buffer); if (end > 0 && buffer[end-1] == '\n') { buffer[end-1] = '\0'; } output.push_back( buffer ); } for( unsigned i = 0; i < output.size(); ++i ) { dprintf( D_FULLDEBUG, "[docker info] %s\n", output[i].c_str() ); } int exitCode = my_pclose( dockerResults ); if( exitCode != 0 ) { dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, output[0].c_str() ); return -3; } #endif return 0; }