/* This function has a unit test. */ int string_to_port( const char* addr ) { const char* acc = addr; const char* tmp; int port = 0; if( ! (addr && is_valid_sinful(addr)) ) { return 0; } if (*acc != '<') return 0; acc++; if (*acc == '[') { tmp = strchr(acc, ']'); if (!tmp) return 0; acc = tmp + 1; } tmp = strchr(acc, ':'); if (!tmp) return 0; tmp++; port = atoi(tmp); return port; }
JICLocalSchedd::JICLocalSchedd( const char* classad_filename, const char* schedd_address, int cluster, int proc, int subproc ) : JICLocalFile( classad_filename, cluster, proc, subproc ) { // initialize this to something reasonable. we'll change it // if anything special happens which needs a different value. exit_code = JOB_EXITED; if( ! is_valid_sinful(schedd_address) ) { EXCEPT("schedd_addr not specified with valid address"); } schedd_addr = strdup( schedd_address ); dprintf( D_ALWAYS, "Starter running a job under a schedd listening at %s\n", schedd_addr ); job_updater = NULL; m_cleanup_retry_tid = -1; m_num_cleanup_retries = 0; // NOTE: these config knobs are very similar to // SHADOW_MAX_JOB_CLEANUP_RETRIES and // SHADOW_JOB_CLEANUP_RETRY_DELAY in the shadow. m_max_cleanup_retries = param_integer("LOCAL_UNIVERSE_MAX_JOB_CLEANUP_RETRIES", 5); m_cleanup_retry_delay = param_integer("LOCAL_UNIVERSE_JOB_CLEANUP_RETRY_DELAY", 30); this->starter_user_policy = NULL; m_tried_notify_job_exit = false; }
static bool test_no_angle_brackets() { emit_test("Is the string correctly rejected if there are no angle brackets?"); char* input = strdup( "209.172.63.167:8080" ); emit_input_header(); emit_param("SINFUL", input); int result = is_valid_sinful( input ); free( input ); emit_output_expected_header(); emit_retval("%s", tfstr(FALSE)); emit_output_actual_header(); emit_retval("%s", tfstr(result)); if(result != FALSE) { FAIL; } PASS; }
static bool test_hostname() { emit_test("Are hostnames instead of IP addresses rejected like they should be?"); char* input = strdup( "<balthazar.cs.wisc.edu:47>" ); emit_input_header(); emit_param("SINFUL", input); int result = is_valid_sinful( input ); free( input ); emit_output_expected_header(); emit_retval("%s", tfstr(FALSE)); emit_output_actual_header(); emit_retval("%s", tfstr(result)); if(result != FALSE) { FAIL; } PASS; }
static bool test_normal_case() { emit_test("Is normal input identified correctly?"); char* input = strdup( "<208.122.19.56:47>" ); emit_input_header(); emit_param("SINFUL", input); int result = is_valid_sinful( input ); free( input ); emit_output_expected_header(); emit_retval("%s", tfstr(TRUE)); emit_output_actual_header(); emit_retval("%s", tfstr(result)); if(result != TRUE) { FAIL; } PASS; }
char* getAddrFromClaimId( const char* id ) { char* tmp; char* addr; char* copy = strdup( id ); tmp = strchr( copy, '#' ); if( tmp ) { *tmp = '\0'; if( is_valid_sinful(copy) ) { addr = strdup( copy ); free( copy ); return addr; } } free( copy ); return NULL; }
bool DCStarter::initFromClassAd( ClassAd* ad ) { char* tmp = NULL; if( ! ad ) { dprintf( D_ALWAYS, "ERROR: DCStarter::initFromClassAd() called with NULL ad\n" ); return false; } ad->LookupString( ATTR_STARTER_IP_ADDR, &tmp ); if( ! tmp ) { // If that's not defined, try ATTR_MY_ADDRESS ad->LookupString( ATTR_MY_ADDRESS, &tmp ); } if( ! tmp ) { dprintf( D_FULLDEBUG, "ERROR: DCStarter::initFromClassAd(): " "Can't find starter address in ad\n" ); return false; } else { if( is_valid_sinful(tmp) ) { New_addr( strnewp(tmp) ); is_initialized = true; } else { dprintf( D_FULLDEBUG, "ERROR: DCStarter::initFromClassAd(): invalid %s in ad (%s)\n", ATTR_STARTER_IP_ADDR, tmp ); } free( tmp ); tmp = NULL; } if( ad->LookupString(ATTR_VERSION, &tmp) ) { New_version( strnewp(tmp) ); free( tmp ); tmp = NULL; } return is_initialized; }
int main(int argc, char *argv[]) { char *arg; int nArgs = 0; // number of args int i, result; char* pool = NULL; char* scheddName = NULL; char* scheddAddr = NULL; MyString method; char *tmp; myDistro->Init( argc, argv ); MyName = condor_basename(argv[0]); config(); #if !defined(WIN32) install_sig_handler(SIGPIPE, SIG_IGN ); #endif // dig around in the config file looking for what the config file says // about getting files from Condor. This defaults with the global variable // initialization. tmp = param( "SANDBOX_TRANSFER_METHOD" ); if ( tmp != NULL ) { method = tmp; free( tmp ); string_to_stm( method, st_method ); } char **args = (char **)malloc(sizeof(char *) * argc); // args if ( ! args) exit(2); // parse the arguments. for( argv++; (arg = *argv); argv++ ) { if( arg[0] == '-' ) { if( ! arg[1] ) { usage(); } switch( arg[1] ) { case 'd': // dprintf to console dprintf_set_tool_debug("TOOL", 0); break; case 'c': args[nArgs] = arg; nArgs++; argv++; if( ! *argv ) { fprintf( stderr, "%s: -constraint requires another argument\n", MyName); exit(1); } args[nArgs] = *argv; nArgs++; break; case 'a': if( arg[2] && arg[2] == 'd' ) { argv++; if( ! *argv ) { fprintf( stderr, "%s: -addr requires another argument\n", MyName); exit(1); } if( is_valid_sinful(*argv) ) { scheddAddr = strdup(*argv); if( ! scheddAddr ) { fprintf( stderr, "Out of Memory!\n" ); exit(1); } } else { fprintf( stderr, "%s: \"%s\" is not a valid address\n", MyName, *argv ); fprintf( stderr, "Should be of the form " "<ip.address.here:port>\n" ); fprintf( stderr, "For example: <123.456.789.123:6789>\n" ); exit( 1 ); } break; } All = true; break; case 'n': // use the given name as the schedd name to connect to argv++; if( ! *argv ) { fprintf( stderr, "%s: -name requires another argument\n", MyName); exit(1); } if ( scheddName ) free(scheddName); scheddName = strdup(*argv); break; case 'p': // use the given name as the central manager to query argv++; if( ! *argv ) { fprintf( stderr, "%s: -pool requires another argument\n", MyName); exit(1); } if( pool ) { free( pool ); } pool = strdup( *argv ); break; case 's': argv++; if( ! *argv ) { fprintf( stderr, "%s: -stm requires another argument\n", MyName); exit(1); } method = *argv; string_to_stm(method, st_method); break; case 'v': version(); break; case 'h': usage(0); break; default: fprintf( stderr, "Unrecognized option: %s\n", arg ); usage(); break; } } else { if( All ) { // If -all is set, there should be no other // constraint arguments. usage(); } args[nArgs] = arg; nArgs++; } } // Check to make sure we have a valid sandbox transfer mechanism. if (st_method == STM_UNKNOWN) { fprintf( stderr, "%s: Unknown sandbox transfer method: %s\n", MyName, method.Value()); usage(); exit(1); } if( ! (All || nArgs) ) { // We got no indication of what to act on fprintf( stderr, "You did not specify any jobs\n" ); usage(); } // We're done parsing args, now make sure we know how to // contact the schedd. if( ! scheddAddr ) { // This will always do the right thing, even if either or // both of scheddName or pool are NULL. schedd = new DCSchedd( scheddName, pool ); } else { schedd = new DCSchedd( scheddAddr ); } if( ! schedd->locate() ) { fprintf( stderr, "%s: %s\n", MyName, schedd->error() ); exit( 1 ); } // Process the args. if( All ) { handleAll(); } else { for(i = 0; i < nArgs; i++) { if( match_prefix( args[i], "-constraint" ) ) { i++; addConstraint( args[i] ); } else { procArg(args[i]); } } } // Sanity check: make certain we now have a constraint if ( global_constraint.Length() <= 0 ) { fprintf( stderr, "Unable to create a job constraint!\n"); exit(1); } fprintf(stdout,"Fetching data files...\n"); switch(st_method) { case STM_USE_SCHEDD_ONLY: { // start block // Get the sandbox directly from the schedd. // And now, do the work. CondorError errstack; result = schedd->receiveJobSandbox(global_constraint.Value(), &errstack); if ( !result ) { fprintf( stderr, "\n%s\n", errstack.getFullText(true).c_str() ); fprintf( stderr, "ERROR: Failed to spool job files.\n" ); exit(1); } // All done return 0; } //end block break; case STM_USE_TRANSFERD: { // start block // NEW METHOD where we ask the schedd for a transferd, then get the // files from the transferd CondorError errstack; ClassAd respad; int invalid; MyString reason; MyString td_sinful; MyString td_cap; result = schedd->requestSandboxLocation(FTPD_DOWNLOAD, global_constraint, FTP_CFTP, &respad, &errstack); if ( !result ) { fprintf( stderr, "\n%s\n", errstack.getFullText(true).c_str() ); fprintf( stderr, "ERROR: Failed to spool job files.\n" ); exit(1); } respad.LookupInteger(ATTR_TREQ_INVALID_REQUEST, invalid); if (invalid == TRUE) { fprintf( stderr, "ERROR: Failed to spool job files.\n" ); respad.LookupString(ATTR_TREQ_INVALID_REASON, reason); fprintf( stderr, "%s\n", reason.Value()); exit(EXIT_FAILURE); } respad.LookupString(ATTR_TREQ_TD_SINFUL, td_sinful); respad.LookupString(ATTR_TREQ_CAPABILITY, td_cap); dprintf(D_ALWAYS, "td: %s, cap: %s\n", td_sinful.Value(), td_cap.Value()); DCTransferD dctd(td_sinful.Value()); result = dctd.download_job_files(&respad, &errstack); if ( !result ) { fprintf( stderr, "\n%s\n", errstack.getFullText(true).c_str() ); fprintf( stderr, "ERROR: Failed to spool job files.\n" ); exit(1); } } // end block break; default: EXCEPT("PROGRAMMER ERROR: st_method must be known."); break; } // All done return 0; }
void BaseShadow::baseInit( ClassAd *job_ad, const char* schedd_addr, const char *xfer_queue_contact_info ) { int pending = FALSE; if( ! job_ad ) { EXCEPT("baseInit() called with NULL job_ad!"); } jobAd = job_ad; if (sendUpdatesToSchedd && ! is_valid_sinful(schedd_addr)) { EXCEPT("schedd_addr not specified with valid address"); } scheddAddr = sendUpdatesToSchedd ? strdup( schedd_addr ) : strdup("noschedd"); m_xfer_queue_contact_info = xfer_queue_contact_info; if ( !jobAd->LookupString(ATTR_OWNER, owner)) { EXCEPT("Job ad doesn't contain an %s attribute.", ATTR_OWNER); } if( !jobAd->LookupInteger(ATTR_CLUSTER_ID, cluster)) { EXCEPT("Job ad doesn't contain a %s attribute.", ATTR_CLUSTER_ID); } if( !jobAd->LookupInteger(ATTR_PROC_ID, proc)) { EXCEPT("Job ad doesn't contain a %s attribute.", ATTR_PROC_ID); } // Grab the GlobalJobId if we've got it. if( ! jobAd->LookupString(ATTR_GLOBAL_JOB_ID, &gjid) ) { gjid = NULL; } // grab the NT domain if we've got it jobAd->LookupString(ATTR_NT_DOMAIN, domain); if ( !jobAd->LookupString(ATTR_JOB_IWD, iwd)) { EXCEPT("Job ad doesn't contain an %s attribute.", ATTR_JOB_IWD); } if( !jobAd->LookupFloat(ATTR_BYTES_SENT, prev_run_bytes_sent) ) { prev_run_bytes_sent = 0; } if( !jobAd->LookupFloat(ATTR_BYTES_RECVD, prev_run_bytes_recvd) ) { prev_run_bytes_recvd = 0; } // construct the core file name we'd get if we had one. MyString tmp_name = iwd; tmp_name += DIR_DELIM_CHAR; tmp_name += "core."; tmp_name += cluster; tmp_name += '.'; tmp_name += proc; core_file_name = strdup( tmp_name.Value() ); // put the shadow's sinful string into the jobAd. Helpful for // the mpi shadow, at least...and a good idea in general. MyString tmp_addr = ATTR_MY_ADDRESS; tmp_addr += "=\""; tmp_addr += daemonCore->InfoCommandSinfulString(); tmp_addr += '"'; if ( !jobAd->Insert( tmp_addr.Value() )) { EXCEPT( "Failed to insert %s!", ATTR_MY_ADDRESS ); } DebugId = display_dprintf_header; config(); // Make sure we've got enough swap space to run checkSwap(); // handle system calls with Owner's privilege // XXX this belong here? We'll see... // Calling init_user_ids() while in user priv causes badness. // Make sure we're in another priv state. set_condor_priv(); if ( !init_user_ids(owner.Value(), domain.Value())) { dprintf(D_ALWAYS, "init_user_ids() failed as user %s\n",owner.Value() ); // uids.C will EXCEPT when we set_user_priv() now // so there's not much we can do at this point #if ! defined(WIN32) if ( param_boolean( "SHADOW_RUN_UNKNOWN_USER_JOBS", false ) ) { dprintf(D_ALWAYS, "trying init_user_ids() as user nobody\n" ); owner="nobody"; domain=NULL; if (!init_user_ids(owner.Value(), domain.Value())) { dprintf(D_ALWAYS, "init_user_ids() failed!\n"); } else { jobAd->Assign( ATTR_JOB_RUNAS_OWNER, "FALSE" ); m_RunAsNobody=true; dprintf(D_ALWAYS, "init_user_ids() now running as user nobody\n"); } } #endif } set_user_priv(); daemonCore->Register_Priv_State( PRIV_USER ); dumpClassad( "BaseShadow::baseInit()", this->jobAd, D_JOB ); // initialize the UserPolicy object shadow_user_policy.init( jobAd, this ); // setup an object to keep our job ad updated to the schedd's // permanent job queue. this clears all the dirty bits on our // copy of the classad, so anything we touch after this will // be updated to the schedd when appropriate. // Unless we got a command line arg asking us not to if (sendUpdatesToSchedd) { // the usual case job_updater = new QmgrJobUpdater( jobAd, scheddAddr, CondorVersion() ); } else { job_updater = new NullQmgrJobUpdater( jobAd, scheddAddr, CondorVersion() ); } // init user log; hold on failure // NOTE: job_updater must be initialized _before_ initUserLog(), // in order to handle the case of the job going on hold as a // result of failure in initUserLog(). initUserLog(); // change directory; hold on failure if ( cdToIwd() == -1 ) { EXCEPT("Could not cd to initial working directory"); } // check to see if this invocation of the shadow is just to write // a terminate event and exit since this job had been recorded as // pending termination, but somehow the job didn't leave the queue // and the schedd is trying to restart it again.. if( jobAd->LookupInteger(ATTR_TERMINATION_PENDING, pending)) { if (pending == TRUE) { // If the classad of this job "thinks" that this job should be // finished already, let's enact that belief. // This function does not return. this->terminateJob(US_TERMINATE_PENDING); } } // If we need to claim the startd before activating the claim int wantClaiming = 0; jobAd->LookupBool(ATTR_CLAIM_STARTD, wantClaiming); if (wantClaiming) { MyString startdSinful; MyString claimid; // Pull startd addr and claimid out of the jobad jobAd->LookupString(ATTR_STARTD_IP_ADDR, startdSinful); jobAd->LookupString(ATTR_CLAIM_ID, claimid); dprintf(D_ALWAYS, "%s is true, trying to claim startd %s\n", ATTR_CLAIM_STARTD, startdSinful.Value()); classy_counted_ptr<DCStartd> startd = new DCStartd("description", NULL, startdSinful.Value(), claimid.Value()); classy_counted_ptr<DCMsgCallback> cb = new DCMsgCallback((DCMsgCallback::CppFunction)&BaseShadow::startdClaimedCB, this, jobAd); // this can't fail, will always call the callback startd->asyncRequestOpportunisticClaim(jobAd, "description", daemonCore->InfoCommandSinfulString(), 1200 /*alive interval*/, 20 /* net timeout*/, 100 /*total timeout*/, cb); } }
void parseArgv( int /*argc*/, char* argv[] ) { char** tmp = argv; for( tmp++; *tmp; tmp++ ) { if( (*tmp)[0] != '-' ) { // If it doesn't start with '-', skip it continue; } switch( (*tmp)[1] ) { // // // // // // // // // // // // // // // // // Shared options that make sense to all cmds // // // // // // // // // // // // // // // // case 'v': if( strncmp("-version", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } version(); break; case 'h': if( strncmp("-help", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } usage( my_name, 0); break; case 'd': if( strncmp("-debug", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } dprintf_set_tool_debug("TOOL", 0); break; case 'a': if( cmd != CA_REQUEST_CLAIM ) { invalid( *tmp ); } if( strncmp("-address", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } tmp++; if( ! (tmp && *tmp) ) { another( "-address" ); } if( ! is_valid_sinful(*tmp) ) { fprintf( stderr, "%s: '%s' is not a valid address\n", my_name, *tmp ); exit( 1 ); } if (addr) { free(addr); } addr = strdup( *tmp ); break; case 'n': if( cmd != CA_REQUEST_CLAIM ) { invalid( *tmp ); } if( strncmp("-name", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } tmp++; if( ! (tmp && *tmp) ) { another( "-name" ); } if (name) { free(name); } name = get_daemon_name( *tmp ); if( ! name ) { fprintf( stderr, "%s: unknown host %s\n", my_name, get_host_part(*tmp) ); exit( 1 ); } break; // // // // // // // // // // // // // // // // // Switches that only make sense to some cmds // // // // // // // // // // // // // // // // case 'f': if( !((cmd == CA_RELEASE_CLAIM) || (cmd == CA_DEACTIVATE_CLAIM)) ) { invalid( *tmp ); } if( strncmp("-fast", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } vacate_type = VACATE_FAST; break; case 'r': if( !((cmd == CA_REQUEST_CLAIM) || (cmd == CA_ACTIVATE_CLAIM)) ) { invalid( *tmp ); } if( strncmp("-requirements", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } tmp++; if( ! (tmp && *tmp) ) { another( "-requirements" ); } if (requirements) { free(requirements); } requirements = strdup( *tmp ); break; case 'i': if( cmd == CA_REQUEST_CLAIM ) { invalid( *tmp ); } if( strncmp("-id", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } tmp++; if( ! (tmp && *tmp) ) { another( "-id" ); } if (claim_id) { free(claim_id); } claim_id = strdup( *tmp ); break; case 'j': if( cmd != CA_ACTIVATE_CLAIM ) { invalid( *tmp ); } if( strncmp("-jobad", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } tmp++; if( ! (tmp && *tmp) ) { another( "-jobad" ); } if (jobad_path) { free(jobad_path); } jobad_path = strdup( *tmp ); break; case 'k': if( cmd != CA_ACTIVATE_CLAIM ) { invalid( *tmp ); } if( strncmp("-keyword", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } tmp++; if( ! (tmp && *tmp) ) { another( "-keyword" ); } if (job_keyword) { free(job_keyword); } job_keyword = strdup( *tmp ); break; // // // // // // // // // // // // // // // // // // // P and C are complicated, since they are ambiguous // in the case of activate, but not others. so, they // have their own methods to make it easier to // understand what the hell's going on. :) // // // // // // // // // // // // // // // // // // case 'l': if( strncmp("-lease", *tmp, strlen(*tmp)) == 0 ) { if( cmd != CA_REQUEST_CLAIM ) { invalid( *tmp ); } tmp++; if( ! (tmp && *tmp) ) { another( "-lease" ); } lease_time = atoi( *tmp ); } else { invalid( *tmp ); } break; case 't': if( strncmp("-timeout", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } tmp++; if( ! (tmp && *tmp) ) { another( "-timeout" ); } timeout = atoi( *tmp ); break; case 'x': if( strncmp("-x509proxy", *tmp, strlen(*tmp)) ) { invalid( *tmp ); } tmp++; if( ! (tmp && *tmp) ) { another( "-x509proxy" ); } proxy_file = *tmp; break; case 'p': parsePOpt( tmp[0], tmp[1] ); tmp++; break; case 'c': parseCOpt( tmp[0], tmp[1] ); tmp++; break; default: invalid( *tmp ); } } // Now that we're done parsing, make sure it all makes sense if( needs_id && ! claim_id ) { fprintf( stderr, "ERROR: You must specify a ClaimID with " "-id for %s\n", my_name ); usage( my_name ); } if( addr && name ) { fprintf( stderr, "ERROR: You cannot specify both -name and -address\n" ); usage( my_name ); } if( addr ) { target = addr; } else if( name ) { target = name; } else if( claim_id ) { // This is the last resort, because claim ids are // no longer considered to be the correct place to // get the startd's address. target = getAddrFromClaimId( claim_id ); } else { // local startd target = NULL; } if( cmd == CA_ACTIVATE_CLAIM && ! (job_keyword || jobad_path) ) { fprintf( stderr, "ERROR: You must specify -keyword or -jobad for %s\n", my_name ); usage( my_name ); } if (cmd == DELEGATE_GSI_CRED_STARTD && !proxy_file) { proxy_file = get_x509_proxy_filename(); if (!proxy_file) { fprintf( stderr, "\nERROR: can't determine proxy filename to delegate\n" ); exit(1); } } if( jobad_path ) { if( ! strcmp(jobad_path, "-") ) { JOBAD_PATH = stdin; } else { JOBAD_PATH = safe_fopen_wrapper_follow( jobad_path, "r" ); if( !JOBAD_PATH ) { fprintf( stderr, "ERROR: failed to open '%s': errno %d (%s)\n", jobad_path, errno, strerror(errno) ); exit( 1 ); } } } if( classad_path ) { CA_PATH = safe_fopen_wrapper_follow( classad_path, "w" ); if( !CA_PATH ) { fprintf( stderr, "ERROR: failed to open '%s': errno %d (%s)\n", classad_path, errno, strerror(errno) ); exit( 1 ); } } }
void parseArgs( int argc, char *argv[] ) { char *opt; char** tmp = argv; for( tmp++; *tmp; tmp++ ) { opt = tmp[0]; if( sscanf(opt, "%d.%d", &cluster, &proc) == 2 ) { if( cluster < 0 || proc < 0 ) { dprintf(D_ALWAYS, "ERROR: invalid cluster.proc specified: %s\n", opt); usage(argc, argv); } continue; } if( opt[0] == '<' ) { // might be the schedd's address if( is_valid_sinful(opt)) { schedd_addr = opt; continue; } else { dprintf(D_ALWAYS, "ERROR: invalid shadow-private schedd_addr specified: %s\n", opt); usage(argc, argv); } } if( !strcmp(opt, "--reconnect") || !strcmp(opt, "-reconnect") ) { is_reconnect = true; continue; } if (strncmp(opt, "--schedd", 8) == 0) { char *ptr = strchr(opt, '<'); if (ptr && is_valid_sinful(ptr)) { public_schedd_addr = ptr; continue; } else { dprintf(D_ALWAYS, "ERROR: invalid public schedd_addr specified: %s\n", opt); usage(argc, argv); } } if (strncmp(opt, "--xfer-queue=", 13) == 0) { xfer_queue_contact_info = opt+13; continue; } if (strcmp(opt, "--no-schedd-updates") == 0) { sendUpdatesToSchedd = false; continue; } // the only other argument we understand is the // filename we should read our ClassAd from, "-" for // STDIN. There's no further checking we need to do if( job_ad_file ) { // already were here, bail out dprintf( D_ALWAYS, "ERROR: unrecognized option (%s)\n", opt ); usage(argc, argv); } job_ad_file = opt; } // A proper model of arguments should be presented here and // used to validate the provided arguments. It would be // something like: // if no cluster/proc, who cares // if no job_ad_file, fail // And that might be it. // The validation used to count arguments processed, which was // easily fooled. }
int main( int argc, char *argv[] ) { char *arg; char **args = (char **)malloc(sizeof(char *)*(argc - 1)); // args int nArgs = 0; // number of args int i; char* cmd_str; DCCollector* pool = NULL; char* scheddName = NULL; char* scheddAddr = NULL; // Initialize our global variables has_constraint = false; myDistro->Init( argc, argv ); MyName = strrchr( argv[0], DIR_DELIM_CHAR ); if( !MyName ) { MyName = argv[0]; } else { MyName++; } cmd_str = strchr( MyName, '_'); // we match modes based on characters after the '_'. This means // 'condor_hold.exe' or 'condor_hold_wrapped' are all legal argv[0]'s // for condor_hold. if (cmd_str && strncasecmp( cmd_str, "_hold", strlen("_hold") ) == MATCH) { mode = JA_HOLD_JOBS; } else if ( cmd_str && strncasecmp( cmd_str, "_release", strlen("_release") ) == MATCH ) { mode = JA_RELEASE_JOBS; } else if ( cmd_str && strncasecmp( cmd_str, "_suspend", strlen("_suspend") ) == MATCH ) { mode = JA_SUSPEND_JOBS; } else if ( cmd_str && strncasecmp( cmd_str, "_continue", strlen("_continue") ) == MATCH ) { mode = JA_CONTINUE_JOBS; }else if ( cmd_str && strncasecmp( cmd_str, "_rm", strlen("_rm") ) == MATCH ) { mode = JA_REMOVE_JOBS; } else if( cmd_str && ! strncasecmp(cmd_str, "_vacate_job", strlen("_vacate_job")) ) { mode = JA_VACATE_JOBS; } else { // don't know what mode we're using, so bail. fprintf( stderr, "Unrecognized command name, \"%s\"\n", MyName ); usage(); } config(); if( argc < 2 ) { // We got no indication of what to act on fprintf( stderr, "You did not specify any jobs\n" ); usage(); } #if !defined(WIN32) install_sig_handler(SIGPIPE, SIG_IGN ); #endif for( argv++; (arg = *argv); argv++ ) { if( arg[0] == '-' ) { if (match_prefix(arg, "-debug")) { // dprintf to console dprintf_set_tool_debug("TOOL", 0); } else if (match_prefix(arg, "-constraint")) { args[nArgs] = arg; nArgs++; argv++; if( ! *argv ) { fprintf( stderr, "%s: -constraint requires another argument\n", MyName); exit(1); } args[nArgs] = *argv; nArgs++; ConstraintArg = true; } else if (match_prefix(arg, "-all")) { All = true; } else if (match_prefix(arg, "-addr")) { argv++; if( ! *argv ) { fprintf( stderr, "%s: -addr requires another argument\n", MyName); exit(1); } if( is_valid_sinful(*argv) ) { scheddAddr = strdup(*argv); if( ! scheddAddr ) { fprintf( stderr, "Out of memory!\n" ); exit(1); } } else { fprintf( stderr, "%s: \"%s\" is not a valid address\n", MyName, *argv ); fprintf( stderr, "Should be of the form " "<ip.address.here:port>\n" ); fprintf( stderr, "For example: <123.456.789.123:6789>\n" ); exit( 1 ); } } else if (match_prefix(arg, "-reason")) { argv++; if( ! *argv ) { fprintf( stderr, "%s: -reason requires another argument\n", MyName); exit(1); } actionReason = strdup(*argv); if( ! actionReason ) { fprintf( stderr, "Out of memory!\n" ); exit(1); } } else if (match_prefix(arg, "-subcode")) { argv++; if( ! *argv ) { fprintf( stderr, "%s: -subcode requires another argument\n", MyName); exit(1); } char *end = NULL; long code = strtol(*argv,&end,10); if( code == LONG_MIN || !end || *end || end==*argv ) { fprintf( stderr, "Invalid -subcode %s!\n", *argv ); exit(1); } holdReasonSubCode = strdup(*argv); ASSERT( holdReasonSubCode ); } else if (match_prefix(arg, "-forcex")) { if( mode == JA_REMOVE_JOBS ) { mode = JA_REMOVE_X_JOBS; } else { fprintf( stderr, "-forcex is only valid with condor_rm\n" ); usage(); } } else if (match_prefix(arg, "-fast")) { if( mode == JA_VACATE_JOBS ) { mode = JA_VACATE_FAST_JOBS; } else { fprintf( stderr, "-fast is only valid with condor_vacate_job\n" ); usage(); } } else if (match_prefix(arg, "-name")) { // use the given name as the schedd name to connect to argv++; if( ! *argv ) { fprintf( stderr, "%s: -name requires another argument\n", MyName); exit(1); } if( !(scheddName = get_daemon_name(*argv)) ) { fprintf( stderr, "%s: unknown host %s\n", MyName, get_host_part(*argv) ); exit(1); } } else if (match_prefix(arg, "-pool")) { // use the given name as the central manager to query argv++; if( ! *argv ) { fprintf( stderr, "%s: -pool requires another argument\n", MyName); exit(1); } if( pool ) { delete pool; } pool = new DCCollector( *argv ); if( ! pool->addr() ) { fprintf( stderr, "%s: %s\n", MyName, pool->error() ); exit(1); } } else if (match_prefix(arg, "-version")) { version(); } else if (match_prefix(arg, "-help")) { usage(0); } else { fprintf( stderr, "Unrecognized option: %s\n", arg ); usage(); } } else { if( All ) { // If -all is set, there should be no other // constraint arguments. usage(); } args[nArgs] = arg; nArgs++; UserJobIdArg = true; } } if( ! (All || nArgs) ) { // We got no indication of what to act on fprintf( stderr, "You did not specify any jobs\n" ); usage(); } if ( ConstraintArg && UserJobIdArg ) { fprintf( stderr, "You can't use both -constraint and usernames or job ids\n" ); usage(); } // Pick the default reason if the user didn't specify one if( actionReason == NULL ) { switch( mode ) { case JA_RELEASE_JOBS: actionReason = strdup("via condor_release"); break; case JA_REMOVE_X_JOBS: actionReason = strdup("via condor_rm -forcex"); break; case JA_REMOVE_JOBS: actionReason = strdup("via condor_rm"); break; case JA_HOLD_JOBS: actionReason = strdup("via condor_hold"); break; case JA_SUSPEND_JOBS: actionReason = strdup("via condor_suspend"); break; case JA_CONTINUE_JOBS: actionReason = strdup("via condor_continue"); break; default: actionReason = NULL; } } // We're done parsing args, now make sure we know how to // contact the schedd. if( ! scheddAddr ) { // This will always do the right thing, even if either or // both of scheddName or pool are NULL. schedd = new DCSchedd( scheddName, pool ? pool->addr() : NULL ); } else { schedd = new DCSchedd( scheddAddr ); } if( ! schedd->locate() ) { fprintf( stderr, "%s: %s\n", MyName, schedd->error() ); exit( 1 ); } // Special case for condor_rm -forcex: a configuration // setting can disable this functionality. The real // validation is done in the schedd, but we can catch // the most common cases here and give a useful error // message. if(mode == JA_REMOVE_X_JOBS) { if( mayUserForceRm() == false) { fprintf( stderr, "Remove aborted. condor_rm -forcex has been disabled by the administrator.\n" ); exit( 1 ); } } // Process the args so we do the work. if( All ) { handleAll(); } else { for(i = 0; i < nArgs; i++) { if( match_prefix( args[i], "-constraint" ) ) { i++; addConstraint( args[i] ); } else { procArg(args[i]); } } } // Deal with all the -constraint constraints handleConstraints(); // Finally, do the actual work for all our args which weren't // constraints... if( job_ids ) { CondorError errstack; ClassAd* result_ad = doWorkByList( job_ids, &errstack ); if (had_error) { fprintf( stderr, "%s\n", errstack.getFullText(true).c_str() ); } printNewMessages( result_ad, job_ids ); delete( result_ad ); } // If releasing jobs, and no errors happened, do a // reschedule command now. if ( mode == JA_RELEASE_JOBS && had_error == false ) { Daemon my_schedd(DT_SCHEDD, NULL, NULL); CondorError errstack; if (!my_schedd.sendCommand(RESCHEDULE, Stream::safe_sock, 0, &errstack)) { fprintf( stderr, "%s\n", errstack.getFullText(true).c_str() ); } } return had_error; }