示例#1
0
/* parse_requeue_args()
 * IN s - string to parse
 * OUT flags - flags to set based upon argument
 * RET 0 on successful parse, -1 otherwise
 */
extern int
parse_requeue_flags(char *s, uint32_t *flags)
{
	char *p, *p0, *z;

	p0 = p = xstrdup(s);
	/* search for =
	 */
	z = strchr(p, '=');
	if (!z) {
		xfree(p0);
		return -1;
	}
	*z = 0;

	/* validate flags keyword
	 */
	if (xstrncasecmp(p, "state", 5)) {
		xfree(p0);
		return -1;
	}
	++z;

	p = z;
	if (!xstrncasecmp(p, "specialexit", 11) || !xstrncasecmp(p, "se", 2)) {
		*flags = JOB_SPECIAL_EXIT;
		xfree(p0);
		return 0;
	}

	xfree(p0);
	return -1;
}
示例#2
0
/*
 * _job_rep - Reports having to do with jobs
 * IN argc - count of arguments
 * IN argv - list of arguments
 */
static void _job_rep (int argc, char **argv)
{
	int error_code = SLURM_SUCCESS;
	int command_len = strlen(argv[0]);

	/* For backwards compatibility we just look at the 1st char
	 * by default since Sizes was the original name */
	if (!xstrncasecmp(argv[0], "SizesByAccount", MAX(command_len, 1))) {
		error_code = job_sizes_grouped_by_top_acct(
			(argc - 1), &argv[1]);
	} else if (!xstrncasecmp(argv[0],
				 "SizesByWcKey", MAX(command_len, 8))) {
		error_code = job_sizes_grouped_by_wckey(
			(argc - 1), &argv[1]);
	} else if (!xstrncasecmp(argv[0],
				"SizesByAccountAndWcKey",
				MAX(command_len, 15))) {
		error_code = job_sizes_grouped_by_top_acct_and_wckey(
			(argc - 1), &argv[1]);
	} else {
		exit_code = 1;
		fprintf(stderr, "Not valid report %s\n", argv[0]);
		fprintf(stderr, "Valid job reports are, ");
		fprintf(stderr, "\"SizesByAccount, SizesByAccountAndWcKey, ");
		fprintf(stderr, "and  SizesByWckey\"\n");
	}

	if (error_code) {
		exit_code = 1;
	}
}
示例#3
0
/*
 * scontrol_requeue - requeue a pending or running batch job
 * IN job_id_str - a job id
 */
extern void
scontrol_requeue(char *job_str)
{
	char *job_id_str;
	int rc, i;
	job_array_resp_msg_t *resp = NULL;

	if (!job_str[0]) {
		exit_code = 1;
		return;
	}

	if (xstrncasecmp(job_str, "jobid=", 6) == 0)
		job_str += 6;
	if (xstrncasecmp(job_str, "job=", 4) == 0)
		job_str += 4;

	if (_is_job_id(job_str)) {
		job_id_str = _next_job_id();
		while (job_id_str) {
			rc = slurm_requeue2(job_id_str, 0, &resp);
			if (rc != SLURM_SUCCESS) {
				exit_code = 1;
				if (quiet_flag != 1) {
					fprintf(stderr, "%s for job %s\n",
						slurm_strerror(slurm_get_errno()),
						job_id_str);
				}
			} else if (resp) {
				for (i = 0; i < resp->job_array_count; i++) {
					if ((resp->error_code[i] == SLURM_SUCCESS)
					    && (resp->job_array_count == 1))
						continue;
					exit_code = 1;
					if (quiet_flag == 1)
						continue;
					fprintf(stderr, "%s: %s\n",
						resp->job_array_id[i],
						slurm_strerror(resp->
							       error_code[i]));
				}
				slurm_free_job_array_resp(resp);
				resp = NULL;
			}
			job_id_str = _next_job_id();
		}
	} else {
		exit_code = 1;
		rc = ESLURM_INVALID_JOB_ID;
		slurm_seterrno(rc);
		if (quiet_flag != 1) {
			fprintf(stderr, "%s for job %s\n",
				slurm_strerror(rc), job_str);
		}
	}
}
示例#4
0
文件: opts.c 项目: cread/slurm
static bool
_node_state_equal (int i, const char *str)
{
	int len = strlen (str);

	if ((xstrncasecmp(node_state_string_compact(i), str, len) == 0) ||
	    (xstrncasecmp(node_state_string(i),         str, len) == 0))
		return (true);
	return (false);
}
示例#5
0
static int _set_sort(char *format)
{
	int command_len = strlen(format);

	if (xstrncasecmp(format, "Name", MAX(command_len, 1)) == 0) {
		sort_flag = SLURMDB_REPORT_SORT_NAME;
	} else if (xstrncasecmp(format, "Time", MAX(command_len, 6)) == 0) {
		sort_flag = SLURMDB_REPORT_SORT_TIME;
	} else {
		fprintf (stderr, "unknown timesort format %s", format);
		return SLURM_ERROR;
	}

	return SLURM_SUCCESS;
}
示例#6
0
/*
 * scontrol_print_layout - print information about the supplied layout
 * IN layout_type - print information about the supplied layout 
 */
extern void
scontrol_print_layout (int argc, char **argv)
{
	int i = 0, tag_len = 0;
	char *tag = NULL, *val = NULL;
	char *layout_type = NULL, *entities = NULL, *type = NULL;
	uint32_t flags = 0;
	layout_info_msg_t *layout_info_ptr = NULL;

	while (i < argc) {
		tag = argv[i];
		tag_len = strlen(tag);
		val = strchr(argv[i], '=');

		if (val) {
			tag_len = val - argv[i];
			val++;
		} else if (argc > i+1) {
			val = argv[i+1];
			i++;
		} else {
			val = NULL;
		}
		if (xstrncasecmp(tag, "layouts", MAX(tag_len, 3)) == 0) {
			layout_type = val;
		} else if (xstrncasecmp(tag, "entity", MAX(tag_len, 3)) == 0) {
			entities = val;
		} else if (xstrncasecmp(tag, "type", MAX(tag_len, 3)) == 0) {
			type = val;
		} else if (xstrncasecmp(tag, "nolayout", MAX(tag_len, 4)) ==0) {
			flags |= LAYOUTS_DUMP_NOLAYOUT;
		} else {
			exit_code = 1;
			if (quiet_flag != 1)
				fprintf (stderr,
					 "invalid option for layouts: %s\n",
					 tag);
		}
		i++;
	}
	if (slurm_load_layout (layout_type, entities, type, flags,
			       &layout_info_ptr) == SLURM_SUCCESS) {
		slurm_print_layout_info ( stdout, layout_info_ptr, one_liner );
		slurm_free_layout_info_msg (layout_info_ptr);
	}

	return;
}
int
next_saved_game(struct ffblk *ffblk)
{
	struct dirent *dp;
	int len;

	memset(ffblk, 0, sizeof *ffblk);

	if (save_dir == NULL)
		return (1);

	while ((dp = readdir(save_dir)) != NULL)
	{
		len = NAMLEN(dp);
		if (len < 4)
			continue;
		if (xstrncasecmp(dp->d_name + len - 4, ".SAV", 4) != 0)
			continue;

		strncpy(ffblk->ff_name, dp->d_name, sizeof ffblk->ff_name);
		ffblk->ff_name[sizeof ffblk->ff_name - 1] = 0;

		return (0);
	}

	return (1);
}
示例#8
0
/*
 * _cluster_rep - Reports having to do with clusters
 * IN argc - count of arguments
 * IN argv - list of arguments
 */
static void _cluster_rep (int argc, char **argv)
{
	int error_code = SLURM_SUCCESS;

	if (xstrncasecmp(argv[0], "AccountUtilizationByUser", 1) == 0) {
		error_code = cluster_account_by_user((argc - 1), &argv[1]);
	} else if ((xstrncasecmp(argv[0], "UserUtilizationByAccount", 18) == 0)
		   || (xstrncasecmp(argv[0], "UA", 2) == 0)) {
		error_code = cluster_user_by_account((argc - 1), &argv[1]);
	} else if ((xstrncasecmp(argv[0], "UserUtilizationByWckey", 18) == 0)
		   || (xstrncasecmp(argv[0], "UW", 2) == 0)) {
		error_code = cluster_user_by_wckey((argc - 1), &argv[1]);
	} else if (xstrncasecmp(argv[0], "Utilization", 2) == 0) {
		error_code = cluster_utilization((argc - 1), &argv[1]);
	} else if (xstrncasecmp(argv[0], "WCKeyUtilizationByUser", 1) == 0) {
		error_code = cluster_wckey_by_user((argc - 1), &argv[1]);
	} else {
		exit_code = 1;
		fprintf(stderr, "Not valid report %s\n", argv[0]);
		fprintf(stderr, "Valid cluster reports are, ");
		fprintf(stderr, "\"AccountUtilizationByUser\", "
			"\"UserUtilizationByAccount\", "
			"\"UserUtilizationByWckey\", \"Utilization\", "
			"and \"WCKeyUtilizationByUser\"\n");
	}

	if (error_code) {
		exit_code = 1;
	}
}
示例#9
0
static int _set_time_format(char *format)
{
	int command_len = strlen(format);

	if (xstrncasecmp(format, "SecPer", MAX(command_len, 6)) == 0) {
		time_format = SLURMDB_REPORT_TIME_SECS_PER;
		time_format_string = "Seconds/Percentage of Total";
	} else if (xstrncasecmp(format, "MinPer", MAX(command_len, 6)) == 0) {
		time_format = SLURMDB_REPORT_TIME_MINS_PER;
		time_format_string = "Minutes/Percentage of Total";
	} else if (xstrncasecmp(format, "HourPer", MAX(command_len, 6)) == 0) {
		time_format = SLURMDB_REPORT_TIME_HOURS_PER;
		time_format_string = "Hours/Percentage of Total";
	} else if (xstrncasecmp(format, "Seconds", MAX(command_len, 1)) == 0) {
		time_format = SLURMDB_REPORT_TIME_SECS;
		time_format_string = "Seconds";
	} else if (xstrncasecmp(format, "Minutes", MAX(command_len, 1)) == 0) {
		time_format = SLURMDB_REPORT_TIME_MINS;
		time_format_string = "Minutes";
	} else if (xstrncasecmp(format, "Hours", MAX(command_len, 1)) == 0) {
		time_format = SLURMDB_REPORT_TIME_HOURS;
		time_format_string = "Hours";
	} else if (xstrncasecmp(format, "Percent", MAX(command_len, 1)) == 0) {
		time_format = SLURMDB_REPORT_TIME_PERCENT;
		time_format_string = "Percentage of Total";
	} else {
		fprintf (stderr, "unknown time format %s", format);
		return SLURM_ERROR;
	}

	return SLURM_SUCCESS;
}
示例#10
0
void GetFailStat(struct XFails *Now, char *FName, int rnum)
{
    DEBUG2("->GetFailStat(struct XFails *Now,char *FName,int rnum %d)", rnum);
    int i;
    FILE *fin;
    int32_t count;
    struct Fdt {
        char Code[6];
        int32_t offset;
        int16_t size;
    } Pul;

    fin = sOpen("FAILS.CDR", "rb", 0);
    count = 44;
    fread(&count, sizeof count, 1, fin); // never written to file
    Swap32bit(count);
    fread(&Pul, sizeof Pul, 1, fin);
    Swap32bit(Pul.offset);
    Swap16bit(Pul.size);
    i = 0;

    while (xstrncasecmp(Pul.Code, FName, 4) != 0 && i < count) {
        fread(&Pul, sizeof Pul, 1, fin);
        Swap32bit(Pul.offset);
        Swap16bit(Pul.size);
        i++;
    }

    if (i == count) {
        fclose(fin);
        return;
    }

    fseek(fin, Pul.offset, SEEK_SET);

    if (rnum < 0) { // Unmanned portion
        do {
            fread(Now, sizeof(struct XFails), 1, fin);
            Swap32bit(Now->per);    // Only need to swap this one since we're checking only that

        } while (Now->per != rnum);
    } else {
        do {
            fread(Now, sizeof(struct XFails), 1, fin);
            Swap32bit(Now->per);
            Swap16bit(Now->code);
            Swap16bit(Now->val);
            Swap16bit(Now->xtra);
            Swap16bit(Now->fail);
        } while (Now->per <= rnum);
    };

    fclose(fin);

    DEBUG1("<-GetFailStat()");
}
示例#11
0
/*
 * scontrol_top_job - Move the specified job ID to the top of the queue for
 *	a given user ID, partition, account, and QOS.
 * IN job_str - a job id
 */
extern void
scontrol_top_job(char *job_id_str)
{
	int rc;

	if (xstrncasecmp(job_id_str, "jobid=", 6) == 0)
		job_id_str += 6;
	if (xstrncasecmp(job_id_str, "job=", 4) == 0)
		job_id_str += 4;

	rc = slurm_top_job(job_id_str);
	if (rc != SLURM_SUCCESS) {
		exit_code = 1;
		if (quiet_flag != 1) {
			fprintf(stderr, "%s for job %s\n",
				slurm_strerror(slurm_get_errno()), job_id_str);
		}
	}
}
示例#12
0
文件: opts.c 项目: cread/slurm
/*
 * _parse_state - convert node state name string to numeric value
 * IN str - state name
 * OUT states - node_state value corresponding to str
 * RET 0 or error code
 */
static int
_node_state_id (char *str)
{
	int i;
	int len = strlen (str);

	for (i = 0; i < NODE_STATE_END; i++) {
		if (_node_state_equal (i, str))
			return (i);
	}

	if (xstrncasecmp("DRAIN", str, len) == 0)
		return NODE_STATE_DRAIN;
	if (xstrncasecmp("DRAINED", str, len) == 0)
		return NODE_STATE_DRAIN | NODE_STATE_IDLE;
	if (xstrncasecmp("ERROR", str, len) == 0)
		return NODE_STATE_ERROR;
	if ((xstrncasecmp("RESV", str, len) == 0) ||
	    (xstrncasecmp("RESERVED", str, len) == 0))
		return NODE_STATE_RES;
	if ((xstrncasecmp("PERFCTRS", str, len) == 0) ||
	    (xstrncasecmp("NPC", str, len) == 0))
		return NODE_STATE_NET;
	if ((xstrncasecmp("DRAINING", str, len) == 0) ||
	    (xstrncasecmp("DRNG", str, len) == 0))
		return NODE_STATE_DRAIN | NODE_STATE_ALLOCATED;
	if (_node_state_equal (NODE_STATE_COMPLETING, str))
		return NODE_STATE_COMPLETING;
	if (xstrncasecmp("NO_RESPOND", str, len) == 0)
		return NODE_STATE_NO_RESPOND;
	if (_node_state_equal (NODE_STATE_POWER_SAVE, str))
		return NODE_STATE_POWER_SAVE;
	if (_node_state_equal (NODE_STATE_POWER_UP, str))
		return NODE_STATE_POWER_UP;
	if (_node_state_equal (NODE_STATE_FAIL, str))
		return NODE_STATE_FAIL;
	if (_node_state_equal (NODE_STATE_MAINT, str))
		return NODE_STATE_MAINT;
	if (_node_state_equal (NODE_STATE_REBOOT, str))
		return NODE_STATE_REBOOT;

	return (-1);
}
示例#13
0
static int _parse_restart_args(int argc,
			       char **argv,
			       uint16_t *stick,
			       char **image_dir)
{
	int i;

	for (i=0; i< argc; i++) {
		if (xstrncasecmp(argv[i], "StickToNodes", 5) == 0) {
			*stick = 1;
		} else if (xstrncasecmp(argv[i], "ImageDir=", 9) == 0) {
			*image_dir = &argv[i][9];
		} else {
			exit_code = 1;
			error("Invalid input: %s", argv[i]);
			error("Request aborted");
			return -1;
		}
	}
	return 0;
}
示例#14
0
文件: xmsg.c 项目: dmilith/ekg2-bsd
static QUERY(xmsg_validate_uid)
{
	char *uid = *(va_arg(ap, char**));
	int *valid = va_arg(ap, int*);
	
	if (uid && !xstrncasecmp(uid, "xmsg:", XMSG_UID_DIROFFSET)) {
		(*valid)++;
		return -1;
	}

	return 0;
}
示例#15
0
文件: sniff.c 项目: 11mariom/ekg2
static QUERY(sniff_validate_uid) {
	char	*uid	= *(va_arg(ap, char **));
	int	*valid	= va_arg(ap, int *);

	if (!uid)
		return 0;

	if (!xstrncasecmp(uid, "sniff:", 6) && uid[6]) {
		(*valid)++;
		return -1;
	}
	return 0;
}
示例#16
0
static int _parse_checkpoint_args(int argc,
				  char **argv,
				  uint16_t *max_wait,
				  char **image_dir)
{
	int i;

	for (i=0; i< argc; i++) {
		if (xstrncasecmp(argv[i], "MaxWait=", 8) == 0) {
			*max_wait = (uint16_t) strtol(&argv[i][8],
						      (char **) NULL, 10);
		} else if (xstrncasecmp(argv[i], "ImageDir=", 9) == 0) {
			*image_dir = &argv[i][9];
		} else {
			exit_code = 1;
			error("Invalid input: %s", argv[i]);
			error("Request aborted");
			return -1;
		}
	}
	return 0;
}
示例#17
0
/*
 * _user_rep - Reports having to do with users
 * IN argc - count of arguments
 * IN argv - list of arguments
 */
static void _user_rep (int argc, char **argv)
{
	int error_code = SLURM_SUCCESS;

	if (xstrncasecmp(argv[0], "Top", 1) == 0) {
		error_code = user_top((argc - 1), &argv[1]);
	} else {
		exit_code = 1;
		fprintf(stderr, "Not valid report %s\n", argv[0]);
		fprintf(stderr, "Valid user reports are, ");
		fprintf(stderr, "\"Top\"\n");
	}

	if (error_code) {
		exit_code = 1;
	}
}
示例#18
0
static int MatchUpItem(const char *text, int loc)
{
	const char *word=MapSynonym(text);
	int ct=0;

	if(word==NULL)
		word=text;

	while(ct<=GameHeader.NumItems)
	{
		if(Items[ct].AutoGet && Items[ct].Location==loc &&
			xstrncasecmp(Items[ct].AutoGet,word,GameHeader.WordLength)==0)
			return(ct);
		ct++;
	}
	return(-1);
}
示例#19
0
/*
 * _resv_rep - Reports having to do with reservations
 * IN argc - count of arguments
 * IN argv - list of arguments
 */
static void _resv_rep (int argc, char **argv)
{
	int error_code = SLURM_SUCCESS;

	if (xstrncasecmp(argv[0], "Utilization", 1) == 0) {
		error_code = resv_utilization((argc - 1), &argv[1]);
	} else {
		exit_code = 1;
		fprintf(stderr, "Not valid report %s\n", argv[0]);
		fprintf(stderr, "Valid reservation reports are, ");
		fprintf(stderr, "\"Utilization\"\n");
	}

	if (error_code) {
		exit_code = 1;
	}
}
示例#20
0
static int WhichWord(const char *word, const char **list)
{
	int n=1;
	int ne=1;
	const char *tp;
	while(ne<=GameHeader.NumWords)
	{
		tp=list[ne];
		if(*tp=='*')
			tp++;
		else
			n=ne;
		if(xstrncasecmp(word,tp,GameHeader.WordLength)==0)
			return(n);
		ne++;
	}
	return(-1);
}
示例#21
0
static const char *MapSynonym(const char *word)
{
	int n=1;
	const char *tp;
	static char lastword[16];	/* Last non synonym */
	while(n<=GameHeader.NumWords)
	{
		tp=Nouns[n];
		if(*tp=='*')
			tp++;
		else
			strcpy(lastword,tp);
		if(xstrncasecmp(word,tp,GameHeader.WordLength)==0)
			return(lastword);
		n++;
	}
	return(NULL);
}
示例#22
0
extern int sacctmgr_list_account(int argc, char **argv)
{
	int rc = SLURM_SUCCESS;
	slurmdb_account_cond_t *acct_cond =
		xmalloc(sizeof(slurmdb_account_cond_t));
 	List acct_list;
	int i=0, cond_set=0, prev_set=0;
	ListIterator itr = NULL;
	ListIterator itr2 = NULL;
	slurmdb_account_rec_t *acct = NULL;
	slurmdb_assoc_rec_t *assoc = NULL;

	int field_count = 0;

	print_field_t *field = NULL;

	List format_list = list_create(slurm_destroy_char);
	List print_fields_list; /* types are of print_field_t */

	acct_cond->with_assocs = with_assoc_flag;

	for (i=0; i<argc; i++) {
		int command_len = strlen(argv[i]);
		if (!xstrncasecmp(argv[i], "Where", MAX(command_len, 5))
		    || !xstrncasecmp(argv[i], "Set", MAX(command_len, 3)))
			i++;
		prev_set = _set_cond(&i, argc, argv, acct_cond, format_list);
		cond_set |=  prev_set;
	}

	if (exit_code) {
		slurmdb_destroy_account_cond(acct_cond);
		FREE_NULL_LIST(format_list);
		return SLURM_ERROR;
	} else if (!list_count(format_list)) {
		slurm_addto_char_list(format_list, "Acc,Des,O");
		if (acct_cond->with_assocs)
			slurm_addto_char_list(format_list,
					      "Cl,ParentN,U,Share,GrpJ,GrpN,"
					      "GrpCPUs,GrpMEM,GrpS,GrpWall,GrpCPUMins,"
					      "MaxJ,MaxN,MaxCPUs,MaxS,MaxW,"
					      "MaxCPUMins,QOS,DefaultQOS");

		if (acct_cond->with_coords)
			slurm_addto_char_list(format_list, "Coord");

	}

	if (!acct_cond->with_assocs && cond_set > 1) {
		if (!commit_check("You requested options that are only valid "
				 "when querying with the withassoc option.\n"
				 "Are you sure you want to continue?")) {
			printf("Aborted\n");
			FREE_NULL_LIST(format_list);
			slurmdb_destroy_account_cond(acct_cond);
			return SLURM_SUCCESS;
		}
	}

	print_fields_list = sacctmgr_process_format_list(format_list);
	FREE_NULL_LIST(format_list);

	if (exit_code) {
		slurmdb_destroy_account_cond(acct_cond);
		FREE_NULL_LIST(print_fields_list);
		return SLURM_ERROR;
	}

	acct_list = slurmdb_accounts_get(db_conn, acct_cond);
	slurmdb_destroy_account_cond(acct_cond);

	if (!acct_list) {
		exit_code=1;
		fprintf(stderr, " Problem with query.\n");
		FREE_NULL_LIST(print_fields_list);
		return SLURM_ERROR;
	}

	itr = list_iterator_create(acct_list);
	itr2 = list_iterator_create(print_fields_list);
	print_fields_header(print_fields_list);

	field_count = list_count(print_fields_list);

	while((acct = list_next(itr))) {
		if (acct->assoc_list) {
			ListIterator itr3 =
				list_iterator_create(acct->assoc_list);
			while((assoc = list_next(itr3))) {
				int curr_inx = 1;
				while((field = list_next(itr2))) {
					switch(field->type) {
					case PRINT_ACCT:
						field->print_routine(
							field, acct->name,
							(curr_inx ==
							 field_count));
						break;
					case PRINT_COORDS:
						field->print_routine(
							field,
							acct->coordinators,
							(curr_inx ==
							 field_count));
						break;
					case PRINT_DESC:
						field->print_routine(
							field,
							acct->description,
							(curr_inx ==
							 field_count));
						break;
					case PRINT_ORG:
						field->print_routine(
							field,
							acct->organization,
							(curr_inx ==
							 field_count));
						break;
					default:
						sacctmgr_print_assoc_rec(
							assoc, field, NULL,
							(curr_inx ==
							 field_count));
						break;
					}
					curr_inx++;
				}
				list_iterator_reset(itr2);
				printf("\n");
			}
			list_iterator_destroy(itr3);
		} else {
			int curr_inx = 1;
			while((field = list_next(itr2))) {
				switch(field->type) {
				case PRINT_QOS:
					field->print_routine(
						field, NULL,
						NULL,
						(curr_inx == field_count));
					break;
				case PRINT_ACCT:
					field->print_routine(
						field, acct->name,
						(curr_inx ==
						 field_count));
					break;
				case PRINT_COORDS:
					field->print_routine(
						field,
						acct->coordinators,
						(curr_inx ==
						 field_count));
					break;
				case PRINT_DESC:
					field->print_routine(
						field, acct->description,
						(curr_inx ==
						 field_count));
					break;
				case PRINT_ORG:
					field->print_routine(
						field, acct->organization,
						(curr_inx ==
						 field_count));
					break;
				default:
					field->print_routine(
						field, NULL,
						(curr_inx == field_count));
					break;
				}
				curr_inx++;
			}
			list_iterator_reset(itr2);
			printf("\n");
		}
	}

	list_iterator_destroy(itr2);
	list_iterator_destroy(itr);
	FREE_NULL_LIST(acct_list);
	FREE_NULL_LIST(print_fields_list);

	return rc;
}
示例#23
0
/*
 * binding_key()
 *
 * analizuje nazwê klawisza i wpisuje akcjê do odpowiedniej mapy.
 *
 * 0/-1.
 */
static int binding_key(struct binding *b, const char *key, int add)
{
    /* debug("Key: %s\n", key); */
    if (!xstrncasecmp(key, ("Alt-"), 4)) {
        unsigned char ch;

#define __key(x, y, z) \
	if (!xstrcasecmp(key + 4, (x))) { \
		b->key = saprintf("Alt-%s", (x)); \
		if (add) { \
			ncurses_binding_map_meta[y] = LIST_ADD2(&bindings, xmemdup(b, sizeof(struct binding))); \
			if (z) \
				ncurses_binding_map_meta[z] = ncurses_binding_map_meta[y]; \
		} \
		return 0; \
	}

        __key("Enter", 13, 0);
        __key("Backspace", KEY_BACKSPACE, 127);
        __key("Home", KEY_HOME, KEY_FIND);
        __key("End", KEY_END, KEY_SELECT);
        __key("Delete", KEY_DC, 0);
        __key("Insert", KEY_IC, 0);
        __key("Left", KEY_LEFT, 0);
        __key("Right", KEY_RIGHT, 0);
        __key("Up", KEY_UP, 0);
        __key("Down", KEY_DOWN, 0);
        __key("PageUp", KEY_PPAGE, 0);
        __key("PageDown", KEY_NPAGE, 0);

#undef __key

        if (xstrlen(key) != 5)
            return -1;

        ch = xtoupper(key[4]);

        b->key = saprintf(("Alt-%c"), ch);	/* XXX Alt-Ó ??? */

        if (add) {
            ncurses_binding_map_meta[ch] = LIST_ADD2(&bindings, xmemdup(b, sizeof(struct binding)));
            if (xisalpha(ch))
                ncurses_binding_map_meta[xtolower(ch)] = ncurses_binding_map_meta[ch];
        }

        return 0;
    }

    if (!xstrncasecmp(key, ("Ctrl-"), 5)) {
        unsigned char ch;

//		if (xstrlen(key) != 6)
//			return -1;
#define __key(x, y, z) \
	if (!xstrcasecmp(key + 5, (x))) { \
		b->key = saprintf("Ctrl-%s", (x)); \
		if (add) { \
			ncurses_binding_map[y] = LIST_ADD2(&bindings, xmemdup(b, sizeof(struct binding))); \
			if (z) \
				ncurses_binding_map[z] = ncurses_binding_map[y]; \
		} \
		return 0; \
	}

        __key("Enter", KEY_CTRL_ENTER, 0);
        __key("Escape", KEY_CTRL_ESCAPE, 0);
        __key("Delete", KEY_CTRL_DC, 0);
        __key("Backspace", KEY_CTRL_BACKSPACE, 0);
        __key("Tab", KEY_CTRL_TAB, 0);

#undef __key

        ch = xtoupper(key[5]);
        b->key = saprintf(("Ctrl-%c"), ch);

        if (add) {
            if (xisalpha(ch))
                ncurses_binding_map[ch - 64] = LIST_ADD2(&bindings, xmemdup(b, sizeof(struct binding)));
            else
                return -1;
        }

        return 0;
    }

    if (xtoupper(key[0]) == 'F' && atoi(key + 1)) {
        int f = atoi(key + 1);

        if (f < 1 || f > 63)
            return -1;

        b->key = saprintf(("F%d"), f);

        if (add)
            ncurses_binding_map[KEY_F(f)] = LIST_ADD2(&bindings, xmemdup(b, sizeof(struct binding)));

        return 0;
    }

#define __key(x, y, z) \
	if (!xstrcasecmp(key, (x))) { \
		b->key = xstrdup((x)); \
		if (add) { \
			ncurses_binding_map[y] = LIST_ADD2(&bindings, xmemdup(b, sizeof(struct binding))); \
			if (z) \
				ncurses_binding_map[z] = ncurses_binding_map[y]; \
		} \
		return 0; \
	}

    __key("Enter", 13, 0);
    __key("Escape", 27, 0);
    __key("Home", KEY_HOME, KEY_FIND);
    __key("End", KEY_END, KEY_SELECT);
    __key("Delete", KEY_DC, 0);
    __key("Insert", KEY_IC, 0);
    __key("Backspace", KEY_BACKSPACE, 127);
    __key("Tab", 9, 0);
    __key("Left", KEY_LEFT, 0);
    __key("Right", KEY_RIGHT, 0);
    __key("Up", KEY_UP, 0);
    __key("Down", KEY_DOWN, 0);
    __key("PageUp", KEY_PPAGE, 0);
    __key("PageDown", KEY_NPAGE, 0);

#undef __key

    return -1;
}
示例#24
0
/*
 * scontrol_update_job - update the slurm job configuration per the supplied
 *	arguments
 * IN argc - count of arguments
 * IN argv - list of arguments
 * RET 0 if no slurm error, errno otherwise. parsing error prints
 *			error message and returns 0
 */
extern int scontrol_update_job(int argc, char **argv)
{
	bool update_size = false;
	int i, update_cnt = 0, rc = SLURM_SUCCESS, rc2;
	char *tag, *val;
	int taglen, vallen;
	job_desc_msg_t job_msg;
	job_array_resp_msg_t *resp = NULL;
	uint32_t job_uid = NO_VAL;

	slurm_init_job_desc_msg (&job_msg);
	for (i = 0; i < argc; i++) {
		char *add_info = NULL;
		tag = argv[i];
		val = strchr(argv[i], '=');
		if (val) {
			taglen = val - argv[i];
			if ((taglen > 0) && ((val[-1] == '+') ||
					     (val[-1] == '-'))) {
				add_info = val - 1;
				taglen--;
			}
			val++;
			vallen = strlen(val);
		} else if (xstrncasecmp(tag, "Nice", MAX(strlen(tag), 2)) == 0){
			/* "Nice" is the only tag that might not have an
			   equal sign, so it is handled specially. */
			job_msg.nice = NICE_OFFSET + 100;
			update_cnt++;
			continue;
		} else if (!val && argv[i + 1]) {
			tag = argv[i];
			taglen = strlen(tag);
			val = argv[++i];
			vallen = strlen(val);
		} else {
			exit_code = 1;
			fprintf (stderr, "Invalid input: %s\n", argv[i]);
			fprintf (stderr, "Request aborted\n");
			return -1;
		}

		if (xstrncasecmp(tag, "JobId", MAX(taglen, 3)) == 0) {
			job_msg.job_id_str = val;
		}
		else if (xstrncasecmp(tag, "AdminComment",
				      MAX(taglen, 3)) == 0) {
			if (add_info) {
				if (add_info[0] == '-') {
					error("Invalid syntax, AdminComment can not be subtracted from.");
					exit_code = 1;
					return 0;
				}
				job_msg.admin_comment = add_info;
				/*
				 * Mark as unset so we know we handled this
				 * correctly as there is a check later to make
				 * sure we know we got a +-.
				 */
				add_info = NULL;
			} else
				job_msg.admin_comment = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ArrayTaskThrottle",
				      MAX(taglen, 10)) == 0) {
			int throttle;
			throttle = strtoll(val, (char **) NULL, 10);
			if (throttle < 0) {
				error("Invalid ArrayTaskThrottle value");
				exit_code = 1;
				return 0;
			}
			job_msg.array_inx = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Comment", MAX(taglen, 3)) == 0) {
			job_msg.comment = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Clusters", MAX(taglen, 8)) == 0) {
			job_msg.clusters = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ClusterFeatures",
				      MAX(taglen, 8)) == 0) {
			job_msg.cluster_features = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "DelayBoot", MAX(taglen, 5)) == 0) {
			int time_sec = time_str2secs(val);
			if (time_sec == NO_VAL) {
				error("Invalid DelayBoot value");
				exit_code = 1;
				return 0;
			}
			job_msg.delay_boot = time_sec;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "TimeLimit", MAX(taglen, 5)) == 0) {
			uint32_t job_current_time, time_limit;

			if (val && ((val[0] == '+') || (val[0] == '-'))) {
				if (add_info) {
					error("Invalid syntax, variations of +=- are not accepted.");
					exit_code = 1;
					return 0;
				}
				add_info = val;
				val++;
			}

			time_limit = time_str2mins(val);
			if (time_limit == NO_VAL) {
				error("Invalid TimeLimit value");
				exit_code = 1;
				return 0;
			}
			if (add_info) {
				if (!job_msg.job_id_str) {
					error("JobId must precede TimeLimit "
					      "increment or decrement");
					exit_code = 1;
					return 0;
				}

				job_current_time = _get_job_time(job_msg.
								 job_id_str);
				if (job_current_time == NO_VAL) {
					exit_code = 1;
					return 0;
				}
				if (add_info[0] == '+') {
					time_limit += job_current_time;
				} else if (time_limit > job_current_time) {
					error("TimeLimit decrement larger than"
					      " current time limit (%u > %u)",
					      time_limit, job_current_time);
					exit_code = 1;
					return 0;
				} else {
					time_limit = job_current_time -
						     time_limit;
				}
				/*
				 * Mark as unset so we know we handled this
				 * correctly as there is a check later to make
				 * sure we know we got a +-.
				 */
				add_info = NULL;
			}
			job_msg.time_limit = time_limit;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "TimeMin", MAX(taglen, 5)) == 0) {
			int time_min = time_str2mins(val);
			if ((time_min < 0) && (time_min != INFINITE)) {
				error("Invalid TimeMin value");
				exit_code = 1;
				return 0;
			}
			job_msg.time_min = time_min;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Priority", MAX(taglen, 2)) == 0) {
			if (parse_uint32(val, &job_msg.priority)) {
				error ("Invalid Priority value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Nice", MAX(taglen, 2)) == 0) {
			long long tmp_nice;
			tmp_nice = strtoll(val, (char **)NULL, 10);
			if (llabs(tmp_nice) > (NICE_OFFSET - 3)) {
				error("Nice value out of range (+/- %u). Value "
				      "ignored", NICE_OFFSET - 3);
				exit_code = 1;
				return 0;
			}
			job_msg.nice = NICE_OFFSET + tmp_nice;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "CPUsPerTask", MAX(taglen, 9))) {
			if (parse_uint16(val, &job_msg.cpus_per_task)) {
				error("Invalid CPUsPerTask value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "CpusPerTres", MAX(taglen, 9))) {
			job_msg.cpus_per_tres = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "NumCPUs", MAX(taglen, 6)) == 0) {
			int min_cpus, max_cpus=0;
			if (!get_resource_arg_range(val, "NumCPUs", &min_cpus,
						   &max_cpus, false) ||
			    (min_cpus <= 0) ||
			    (max_cpus && (max_cpus < min_cpus))) {
				error ("Invalid NumCPUs value: %s", val);
				exit_code = 1;
				return 0;
			}
			job_msg.min_cpus = min_cpus;
			if (max_cpus)
				job_msg.max_cpus = max_cpus;
			update_cnt++;
		}
		/* ReqProcs was removed in Slurm version 2.1 */
		else if ((xstrncasecmp(tag, "NumTasks", MAX(taglen, 8)) == 0) ||
			 (xstrncasecmp(tag, "ReqProcs", MAX(taglen, 8)) == 0)) {
			if (parse_uint32(val, &job_msg.num_tasks)) {
				error ("Invalid NumTasks value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Requeue", MAX(taglen, 4)) == 0) {
			if (parse_uint16(val, &job_msg.requeue)) {
				error ("Invalid Requeue value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		/* ReqNodes was replaced by NumNodes in Slurm version 2.1 */
		else if ((xstrncasecmp(tag, "ReqNodes", MAX(taglen, 8)) == 0) ||
		         (xstrncasecmp(tag, "NumNodes", MAX(taglen, 8)) == 0)) {
			int min_nodes, max_nodes, rc;
			if (xstrcmp(val, "0") == 0) {
				job_msg.min_nodes = 0;
			} else if (xstrcasecmp(val, "ALL") == 0) {
				job_msg.min_nodes = INFINITE;
			} else {
				min_nodes = (int) job_msg.min_nodes;
				max_nodes = (int) job_msg.max_nodes;
				rc = get_resource_arg_range(
						val, "requested node count",
						&min_nodes, &max_nodes, false);
				if (!rc)
					return rc;
				job_msg.min_nodes = (uint32_t) min_nodes;
				job_msg.max_nodes = (uint32_t) max_nodes;
			}
			update_size = true;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ReqSockets", MAX(taglen, 4)) == 0) {
			if (parse_uint16(val, &job_msg.sockets_per_node)) {
				error ("Invalid ReqSockets value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ReqCores", MAX(taglen, 4)) == 0) {
			if (parse_uint16(val, &job_msg.cores_per_socket)) {
				error ("Invalid ReqCores value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
                else if (xstrncasecmp(tag, "TasksPerNode", MAX(taglen, 2))==0) {
			if (parse_uint16(val, &job_msg.ntasks_per_node)) {
				error ("Invalid TasksPerNode value: %s", val);
				exit_code = 1;
				return 0;
			}
                        update_cnt++;
                }
		else if (xstrncasecmp(tag, "ReqThreads", MAX(taglen, 4)) == 0) {
			if (parse_uint16(val, &job_msg.threads_per_core)) {
				error ("Invalid ReqThreads value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "MinCPUsNode", MAX(taglen, 4)) == 0) {
			if (parse_uint16(val, &job_msg.pn_min_cpus)) {
				error ("Invalid MinCPUsNode value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "MinMemoryNode",
				     MAX(taglen, 10)) == 0) {
			if (parse_uint64(val, &job_msg.pn_min_memory)) {
				error ("Invalid MinMemoryNode value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "MinMemoryCPU",
				     MAX(taglen, 10)) == 0) {
			if (parse_uint64(val, &job_msg.pn_min_memory)) {
				error ("Invalid MinMemoryCPU value: %s", val);
				exit_code = 1;
				return 0;
			}
			job_msg.pn_min_memory |= MEM_PER_CPU;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "MinTmpDiskNode",
				     MAX(taglen, 5)) == 0) {
			if (parse_uint32(val, &job_msg.pn_min_tmp_disk)) {
				error ("Invalid MinTmpDiskNode value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Partition", MAX(taglen, 2)) == 0) {
			job_msg.partition = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "QOS", MAX(taglen, 2)) == 0) {
			job_msg.qos = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ReservationName",
				     MAX(taglen, 3)) == 0) {
			job_msg.reservation = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "Name", MAX(taglen, 2)) ||
			 !xstrncasecmp(tag, "JobName", MAX(taglen, 4))) {
			job_msg.name = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "WCKey", MAX(taglen, 1)) == 0) {
			job_msg.wckey = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "StdOut", MAX(taglen, 6)) == 0) {
			job_msg.std_out = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Switches", MAX(taglen, 5)) == 0) {
			char *sep_char;
			job_msg.req_switch =
				(uint32_t) strtol(val, &sep_char, 10);
			update_cnt++;
			if (sep_char && sep_char[0] == '@') {
				job_msg.wait4switch = time_str2mins(sep_char+1)
						      * 60;
			}
		}
		else if (xstrncasecmp(tag, "wait-for-switch", MAX(taglen, 5))
			 == 0) {
			if (parse_uint32(val, &job_msg.wait4switch)) {
				error ("Invalid wait-for-switch value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "OverSubscribe", MAX(taglen, 2)) ||
			 !xstrncasecmp(tag, "Shared", MAX(taglen, 2))) {
			if (xstrncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				job_msg.shared = 1;
			else if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				job_msg.shared = 0;
			else if (parse_uint16(val, &job_msg.shared)) {
				error("Invalid OverSubscribe value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Contiguous", MAX(taglen, 3)) == 0) {
			if (xstrncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				job_msg.contiguous = 1;
			else if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				job_msg.contiguous = 0;
			else if (parse_uint16(val, &job_msg.contiguous)) {
				error ("Invalid Contiguous value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "CoreSpec", MAX(taglen, 4)) == 0) {
			if (!xstrcmp(val, "-1") || !xstrcmp(val, "*"))
				job_msg.core_spec = INFINITE16;
			else if (parse_uint16(val, &job_msg.core_spec)) {
				error ("Invalid CoreSpec value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "MemPerTres", MAX(taglen, 5))) {
			job_msg.mem_per_tres = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ThreadSpec", MAX(taglen, 4)) == 0) {
			if (!xstrcmp(val, "-1") || !xstrcmp(val, "*"))
				job_msg.core_spec = INFINITE16;
			else if (parse_uint16(val, &job_msg.core_spec)) {
				error ("Invalid ThreadSpec value: %s", val);
				exit_code = 1;
				return 0;
			} else
				job_msg.core_spec |= CORE_SPEC_THREAD;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresBind", MAX(taglen, 5))) {
			job_msg.tres_bind = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresFreq", MAX(taglen, 5))) {
			job_msg.tres_freq = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresPerJob", MAX(taglen, 8))) {
			job_msg.tres_per_job = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresPerNode", MAX(taglen, 8))) {
			/* "gres" replaced by "tres_per_node" in v18.08 */
			if (job_msg.tres_per_node)
				xstrfmtcat(job_msg.tres_per_node, ",%s", val);
			else
				job_msg.tres_per_node = xstrdup(val);
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresPerSocket", MAX(taglen, 8))) {
			job_msg.tres_per_socket = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "TresPerTask", MAX(taglen, 8))) {
			job_msg.tres_per_task = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "ExcNodeList", MAX(taglen, 3)) == 0){
			job_msg.exc_nodes = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "NodeList",    MAX(taglen, 8)) ||
			 !xstrncasecmp(tag, "ReqNodeList", MAX(taglen, 8))) {
			job_msg.req_nodes = val;
			update_size = true;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Features", MAX(taglen, 1)) == 0) {
			job_msg.features = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Gres", MAX(taglen, 2)) == 0) {
			/* "gres" replaced by "tres_per_node" in v18.08 */
			if (!xstrcasecmp(val, "help") ||
			    !xstrcasecmp(val, "list")) {
				print_gres_help();
			} else if (job_msg.tres_per_node) {
				xstrfmtcat(job_msg.tres_per_node, ",%s", val);
			} else {
				job_msg.tres_per_node = xstrdup(val);
				update_cnt++;
			}
		}
		else if (xstrncasecmp(tag, "Account", MAX(taglen, 1)) == 0) {
			job_msg.account = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "BurstBuffer", MAX(taglen, 1)) == 0) {
			job_msg.burst_buffer = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Dependency", MAX(taglen, 1)) == 0) {
			job_msg.dependency = val;
			update_cnt++;
		}
		else if (xstrncasecmp(tag, "Licenses", MAX(taglen, 1)) == 0) {
			job_msg.licenses = val;
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "EligibleTime", MAX(taglen, 2)) ||
			 !xstrncasecmp(tag, "StartTime",    MAX(taglen, 2))) {
			if ((job_msg.begin_time = parse_time(val, 0))) {
				if (job_msg.begin_time < time(NULL))
					job_msg.begin_time = time(NULL);
				update_cnt++;
			}
		}
		else if (!xstrncasecmp(tag, "EndTime", MAX(taglen, 2))) {
			job_msg.end_time = parse_time(val, 0);
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "Reboot", MAX(taglen, 3))) {
			if (xstrncasecmp(val, "YES", MAX(vallen, 1)) == 0)
				job_msg.reboot = 1;
			else if (xstrncasecmp(val, "NO", MAX(vallen, 1)) == 0)
				job_msg.reboot = 0;
			else if (parse_uint16(val, &job_msg.reboot)) {
				error ("Invalid reboot value: %s", val);
				exit_code = 1;
				return 0;
			}
			update_cnt++;
		}
		else if (!xstrncasecmp(tag, "UserID", MAX(taglen, 3))) {
			uid_t user_id = 0;
			if (uid_from_string(val, &user_id) < 0) {
				exit_code = 1;
				fprintf (stderr, "Invalid UserID: %s\n", val);
				fprintf (stderr, "Request aborted\n");
				return 0;
			}
			job_uid = (uint32_t) user_id;
		}
		else if (!xstrncasecmp(tag, "Deadline", MAX(taglen, 3))) {
			if ((job_msg.deadline = parse_time(val, 0))) {
				update_cnt++;
			}
		}
		else {
			exit_code = 1;
			fprintf (stderr, "Update of this parameter is not "
				 "supported: %s\n", argv[i]);
			fprintf (stderr, "Request aborted\n");
			return 0;
		}

		if (add_info) {
			error("Option %s does not accept [+|-]= syntax", tag);
			exit_code = 1;
			return 0;
		}
	}

	if (update_cnt == 0) {
		exit_code = 1;
		fprintf (stderr, "No changes specified\n");
		return 0;
	}

	/* If specified, override uid with effective uid provided by
	 * -u <uid> or --uid=<uid> */
	if (euid != NO_VAL)
		job_msg.user_id = euid;

	if (!job_msg.job_id_str && job_msg.name) {
		/* Translate name to job ID string */
		job_msg.job_id_str = _job_name2id(job_msg.name, job_uid);
		if (!job_msg.job_id_str) {
			exit_code = 1;
			return 0;
		}
	}

	if (!job_msg.job_id_str) {
		error("No job ID specified");
		exit_code = 1;
		return 0;
	}

	if (update_size && !_is_single_job(job_msg.job_id_str)) {
		exit_code = 1;
		return 0;
	}

	if (_is_job_id(job_msg.job_id_str)) {
		job_msg.job_id_str = _next_job_id();
		while (job_msg.job_id_str) {
			rc2 = slurm_update_job2(&job_msg, &resp);
			if (update_size && (rc2 == SLURM_SUCCESS)) {
				/* See check above for one job ID */
				job_msg.job_id = slurm_atoul(job_msg.job_id_str);
				_update_job_size(job_msg.job_id);
			}
			if (rc2 != SLURM_SUCCESS) {
				rc2 = slurm_get_errno();
				rc = MAX(rc, rc2);
				exit_code = 1;
				if (quiet_flag != 1) {
					fprintf(stderr, "%s for job %s\n",
						slurm_strerror(slurm_get_errno()),
						job_msg.job_id_str);
				}
			} else if (resp) {
				for (i = 0; i < resp->job_array_count; i++) {
					if ((resp->error_code[i] == SLURM_SUCCESS)
					    && (resp->job_array_count == 1))
						continue;
					exit_code = 1;
					if (quiet_flag == 1)
						continue;
					fprintf(stderr, "%s: %s\n",
						resp->job_array_id[i],
						slurm_strerror(resp->
							       error_code[i]));
				}
				slurm_free_job_array_resp(resp);
				resp = NULL;
			}
			job_msg.job_id_str = _next_job_id();
		}
	} else if (job_msg.job_id_str) {
		exit_code = 1;
		rc = ESLURM_INVALID_JOB_ID;
		slurm_seterrno(rc);
		if (quiet_flag != 1) {
			fprintf(stderr, "%s for job %s\n",
				slurm_strerror(rc), job_msg.job_id_str);
		}
	}

	return rc;
}
示例#25
0
extern int sacctmgr_modify_account(int argc, char **argv)
{
	int rc = SLURM_SUCCESS;
	slurmdb_account_cond_t *acct_cond =
		xmalloc(sizeof(slurmdb_account_cond_t));
	slurmdb_account_rec_t *acct = xmalloc(sizeof(slurmdb_account_rec_t));
	slurmdb_assoc_rec_t *assoc =
		xmalloc(sizeof(slurmdb_assoc_rec_t));

	int i=0;
	int cond_set = 0, prev_set = 0, rec_set = 0, set = 0;
	List ret_list = NULL;

	slurmdb_init_assoc_rec(assoc, 0);

	for (i=0; i<argc; i++) {
		int command_len = strlen(argv[i]);
		if (!xstrncasecmp(argv[i], "Where", MAX(command_len, 5))) {
			i++;
			prev_set = _set_cond(&i, argc, argv, acct_cond, NULL);
			cond_set |= prev_set;
		} else if (!xstrncasecmp(argv[i], "Set", MAX(command_len, 3))) {
			i++;
			prev_set = _set_rec(&i, argc, argv, NULL, NULL,
					    acct, assoc);
			rec_set |= prev_set;
		} else {
			prev_set = _set_cond(&i, argc, argv, acct_cond, NULL);
			cond_set |= prev_set;
		}
	}

	if (exit_code) {
		slurmdb_destroy_account_cond(acct_cond);
		slurmdb_destroy_account_rec(acct);
		slurmdb_destroy_assoc_rec(assoc);
		return SLURM_ERROR;
	} else if (!rec_set) {
		exit_code=1;
		fprintf(stderr, " You didn't give me anything to set\n");
		slurmdb_destroy_account_cond(acct_cond);
		slurmdb_destroy_account_rec(acct);
		slurmdb_destroy_assoc_rec(assoc);
		return SLURM_ERROR;
	} else if (!cond_set) {
		if (!commit_check("You didn't set any conditions with 'WHERE'.\n"
				 "Are you sure you want to continue?")) {
			printf("Aborted\n");
			slurmdb_destroy_account_cond(acct_cond);
			slurmdb_destroy_account_rec(acct);
			slurmdb_destroy_assoc_rec(assoc);
			return SLURM_SUCCESS;
		}
	}

	// Special case:  reset raw usage only
	if (assoc->usage) {
		rc = SLURM_ERROR;
		if (assoc->usage->usage_raw == 0.0)
			rc = sacctmgr_remove_assoc_usage(acct_cond->assoc_cond);
		else
			error("Raw usage can only be set to 0 (zero)");

		slurmdb_destroy_account_cond(acct_cond);
		slurmdb_destroy_account_rec(acct);
		slurmdb_destroy_assoc_rec(assoc);
		return rc;
	}

	notice_thread_init();
	if (rec_set & 1) { // process the account changes
		if (cond_set == 2) {
			exit_code=1;
			fprintf(stderr,
				" There was a problem with your "
				"'where' options.\n");
			rc = SLURM_ERROR;
			goto assoc_start;
		}
		ret_list = slurmdb_accounts_modify(
			db_conn, acct_cond, acct);
		if (ret_list && list_count(ret_list)) {
			char *object = NULL;
			ListIterator itr = list_iterator_create(ret_list);
			printf(" Modified accounts...\n");
			while((object = list_next(itr))) {
				printf("  %s\n", object);
			}
			list_iterator_destroy(itr);
			set = 1;
		} else if (ret_list) {
			printf(" Nothing modified\n");
			rc = SLURM_ERROR;
		} else {
			exit_code=1;
			fprintf(stderr, " Error with request: %s\n",
				slurm_strerror(errno));

			rc = SLURM_ERROR;
		}

		FREE_NULL_LIST(ret_list);
	}

assoc_start:
	if (rec_set == 3 || rec_set == 2) { // process the association changes
		if (cond_set == 1 && !acct_cond->assoc_cond->acct_list) {
			rc = SLURM_ERROR;
			exit_code=1;
			fprintf(stderr,
				" There was a problem with your "
				"'where' options.\n");
			goto assoc_end;
		}

		if (assoc->parent_acct) {
			slurmdb_account_rec_t *acct_rec =
				sacctmgr_find_account(assoc->parent_acct);
			if (!acct_rec) {
				exit_code=1;
				fprintf(stderr,
					" Parent Account %s doesn't exist.\n",
					assoc->parent_acct);
				rc = SLURM_ERROR;
				goto assoc_end;
			}
		}

		ret_list = slurmdb_associations_modify(
			db_conn, acct_cond->assoc_cond, assoc);

		if (ret_list && list_count(ret_list)) {
			set = 1;
			if (assoc->def_qos_id != NO_VAL)
				set = sacctmgr_check_default_qos(
					     assoc->def_qos_id,
					     acct_cond->assoc_cond);
			else if (assoc->qos_list)
				set = sacctmgr_check_default_qos(
					     -1, acct_cond->assoc_cond);

			if (set) {
				char *object = NULL;
				ListIterator itr = list_iterator_create(
					ret_list);
				printf(" Modified account associations...\n");
				while((object = list_next(itr))) {
					printf("  %s\n", object);
				}
				list_iterator_destroy(itr);
				set = 1;
			}
		} else if (ret_list) {
			printf(" Nothing modified\n");
			rc = SLURM_ERROR;
		} else {
			exit_code=1;
			fprintf(stderr, " Error with request: %s\n",
				slurm_strerror(errno));

			rc = SLURM_ERROR;
		}

		FREE_NULL_LIST(ret_list);
	}

assoc_end:

	notice_thread_fini();
	if (set) {
		if (commit_check("Would you like to commit changes?"))
			slurmdb_connection_commit(db_conn, 1);
		else {
			printf(" Changes Discarded\n");
			slurmdb_connection_commit(db_conn, 0);
		}
	}
	slurmdb_destroy_account_cond(acct_cond);
	slurmdb_destroy_account_rec(acct);
	slurmdb_destroy_assoc_rec(assoc);

	return rc;
}
示例#26
0
/*
 * scontrol_print_layout - print information about the supplied layout
 * IN argc - count of arguments
 * IN argv - list of arguments
 * RET 0 if no slurm error, errno otherwise. parsing error prints
 *			error message and returns 0
 */
extern int
scontrol_update_layout (int argc, char **argv)
{
	int rc = 0;
	int i = 0, tag_len = 0;
	char *tag = NULL, *val = NULL;
	update_layout_msg_t msg;
	char *opt = NULL;

	opt = xstrdup_printf(" ");
	memset(&msg, 0, sizeof(update_layout_msg_t));
	while (i < argc) {
		tag = argv[i];
		val = strchr(argv[i], '=');
		if (val) {
			tag_len = val - argv[i];
			val++;
		} else {
			exit_code = 1;
			fprintf (stderr,
				 "invalid option:%s for layouts "
				 "(\"=\" mandatory)\n",
				 tag);
			goto done;
		}
		if (xstrncasecmp(tag, "layouts", MAX(tag_len, 2)) == 0) {
			msg.layout = val;
		} else if (xstrncasecmp(tag, "entity", MAX(tag_len, 2)) == 0) {
			msg.arg = xstrdup_printf("Entity=%s", val);
		} else {
			xstrcat(opt, tag);
			xstrcat(opt, " ");
		}
		i++;
	}

	if (msg.layout == NULL) {
		exit_code = 1;
		fprintf (stderr,
			 "No valid layout name in update command\n");
		goto done;
	}
	if (msg.arg == NULL) {
		exit_code = 1;
		fprintf (stderr,
			 "No valid layout enity in update command\n");
		goto done;
	}
	if ( strlen(opt) <= 1 ) {
		exit_code = 1;
		fprintf (stderr,
			 "No valid updates arguments in update command\n");
		goto done;
	}

	xstrcat(msg.arg, opt);

	rc = slurm_update_layout(&msg);

done:	xfree(msg.arg);
	xfree(opt);
	if (rc) {	
		exit_code = 1;
		return slurm_get_errno ();
	} else
		return 0;
}
示例#27
0
/*
 * scontrol_hold - perform some job hold/release operation
 * IN op	- hold/release operation
 * IN job_str	- a job ID or job name
 * RET 0 if no slurm error, errno otherwise. parsing error prints
 *		error message and returns 0
 */
extern int
scontrol_hold(char *op, char *job_str)
{
	static uint32_t last_job_id = NO_VAL;
	static job_info_msg_t *jobs = NULL;
	job_array_resp_msg_t *resp = NULL;
	int i, rc = SLURM_SUCCESS, rc2;
	int j;
	job_desc_msg_t job_msg;
	uint32_t job_id = 0;
	char *job_name = NULL;
	char *job_id_str = NULL;
	slurm_job_info_t *job_ptr;

	if (job_str && !xstrncasecmp(job_str, "JobID=", 6))
		job_str += 6;
	if (job_str && !xstrncasecmp(job_str, "Job=", 4))
		job_str += 4;

	slurm_init_job_desc_msg (&job_msg);
	if ((xstrncasecmp(op, "holdu", 5) == 0) ||
	    (xstrncasecmp(op, "uhold", 5) == 0)) {
		job_msg.priority = 0;
		job_msg.alloc_sid = ALLOC_SID_USER_HOLD;
	} else if (xstrncasecmp(op, "hold", 4) == 0) {
		job_msg.priority = 0;
		job_msg.alloc_sid = 0;
	} else
		job_msg.priority = INFINITE;

	if (_is_job_id(job_str)) {
		while ((job_msg.job_id_str = _next_job_id())) {
			rc2 = slurm_update_job2(&job_msg, &resp);
			if (rc2 != SLURM_SUCCESS) {
				rc2 = slurm_get_errno();
				rc = MAX(rc, rc2);
				exit_code = 1;
				if (quiet_flag != 1) {
					fprintf(stderr, "%s for job %s\n",
						slurm_strerror(rc2),
						job_msg.job_id_str);
				}
			} else if (resp) {
				for (i = 0; i < resp->job_array_count; i++) {
					if ((resp->error_code[i]==SLURM_SUCCESS)
					    && (resp->job_array_count == 1))
						continue;
					exit_code = 1;
					if (quiet_flag == 1)
						continue;
					fprintf(stderr, "%s: %s\n",
						resp->job_array_id[i],
						slurm_strerror(resp->
							       error_code[i]));
				}
				slurm_free_job_array_resp(resp);
				resp = NULL;
			}
			job_msg.job_id_str = _next_job_id();
		}
		return rc;
	} else if (job_str) {
		if (!xstrncasecmp(job_str, "Name=", 5)) {
			job_str += 5;
			job_id = 0;
			job_name = job_str;
			last_job_id = NO_VAL;
		} else {
			exit_code = 1;
			rc = ESLURM_INVALID_JOB_ID;
			slurm_seterrno(rc);
			if (quiet_flag != 1) {
				fprintf(stderr, "%s for job %s\n",
					slurm_strerror(rc), job_str);
			}
			return rc;
		}
	} else {
		last_job_id = NO_VAL;	/* Refresh cache on next call */
		return 0;
	}

	if (last_job_id != job_id) {
		if (scontrol_load_job(&jobs, job_id)) {
			if (quiet_flag == -1)
				slurm_perror ("slurm_load_job error");
			return 1;
		}
		last_job_id = job_id;
	}

	/* set current user, needed e.g., for AllowGroups checks */
	for (i = 0, job_ptr = jobs->job_array; i < jobs->record_count;
	     i++, job_ptr++) {
		if (xstrcmp(job_name, job_ptr->name))
			continue;

		if (!IS_JOB_PENDING(job_ptr)) {
			if (job_ptr->array_task_id != NO_VAL)
				continue;
			slurm_seterrno(ESLURM_JOB_NOT_PENDING);
			rc = MAX(rc, ESLURM_JOB_NOT_PENDING);
		}

		if (job_ptr->array_task_str) {
			xstrfmtcat(job_id_str, "%u_%s",
				   job_ptr->array_job_id,
				   job_ptr->array_task_str);
		} else if (job_ptr->array_task_id != NO_VAL) {
			xstrfmtcat(job_id_str, "%u_%u",
				   job_ptr->array_job_id,
				   job_ptr->array_task_id);
		} else {
			xstrfmtcat(job_id_str, "%u", job_ptr->job_id);
		}
		job_msg.job_id_str = job_id_str;
		rc2 = slurm_update_job2(&job_msg, &resp);
		if (rc2 != SLURM_SUCCESS) {
			rc2 = slurm_get_errno();
			rc = MAX(rc, rc2);
			exit_code = 1;
			if (quiet_flag != 1) {
				fprintf(stderr, "%s for job %s\n",
					slurm_strerror(rc2),
					job_msg.job_id_str);
			}
		} else if (resp) {
			for (j = 0; j < resp->job_array_count; j++) {
				if ((resp->error_code[j] == SLURM_SUCCESS) &&
				    (resp->job_array_count == 1))
					continue;
				exit_code = 1;
				if (quiet_flag == 1)
					continue;
				fprintf(stderr, "%s: %s\n",
					resp->job_array_id[j],
					slurm_strerror(resp->error_code[j]));
			}
			slurm_free_job_array_resp(resp);
			resp = NULL;
		}
		xfree(job_id_str);
	}

	return rc;
}
示例#28
0
/* sacctmgr_list_tres()
 */
int sacctmgr_list_tres(int argc, char **argv)
{
	List tres_list;
	ListIterator itr;
	ListIterator itr2;
	List format_list = list_create(slurm_destroy_char);
	List print_fields_list;
	slurmdb_tres_cond_t *tres_cond = xmalloc(sizeof(slurmdb_tres_cond_t));
	slurmdb_tres_rec_t *tres;
	int field_count, i;
	print_field_t *field;

    	for (i=0; i<argc; i++) {
		int command_len = strlen(argv[i]);
		if (!xstrncasecmp(argv[i], "Where", MAX(command_len, 5))
		    || !xstrncasecmp(argv[i], "Set", MAX(command_len, 3)))
			i++;
		_set_cond(&i, argc, argv, tres_cond, format_list);
	}

	if (exit_code) {
		slurmdb_destroy_tres_cond(tres_cond);
		FREE_NULL_LIST(format_list);
		return SLURM_ERROR;
	}

	if (!list_count(format_list)) {
		/* Append to the format list the fields
		 * we want to print, these are the data structure
		 * members of the type returned by slurmdbd
		 */
		slurm_addto_char_list(format_list, "Type,Name%15,ID");
	}

	tres_list = slurmdb_tres_get(db_conn, tres_cond);
	slurmdb_destroy_tres_cond(tres_cond);

	if (!tres_list) {
		exit_code=1;
		fprintf(stderr, " Problem with query.\n");
		FREE_NULL_LIST(format_list);
		return SLURM_ERROR;
	}


	/* Process the format list creating a list of
	 * print field_t structures
	 */
	print_fields_list = sacctmgr_process_format_list(format_list);
	FREE_NULL_LIST(format_list);

	itr = list_iterator_create(tres_list);
	itr2 = list_iterator_create(print_fields_list);
	print_fields_header(print_fields_list);
	field_count = list_count(print_fields_list);

	/* For each tres prints the data structure members
	 */
	while ((tres = list_next(itr))) {
		while ((field = list_next(itr2))) {
			switch (field->type) {
				case PRINT_NAME:
					field->print_routine(field,
							     tres->name,
							     field_count);
					break;
				case PRINT_ID:
					field->print_routine(field,
							     tres->id,
							     field_count);
					break;
				case PRINT_TYPE:
					field->print_routine(field,
							     tres->type,
							     field_count);
					break;
			}
		}
		list_iterator_reset(itr2);
		printf("\n");
	}
	list_iterator_destroy(itr);
	list_iterator_destroy(itr2);
	FREE_NULL_LIST(tres_list);
	FREE_NULL_LIST(print_fields_list);

	return 0;
}
示例#29
0
static int _set_cond(int *start, int argc, char **argv,
		     slurmdb_tres_cond_t *tres_cond,
		     List format_list)
{
	int i;
	int set = 0;
	int end = 0;
	int command_len = 0;

	if (!tres_cond) {
		exit_code=1;
		fprintf(stderr, "No tres_cond given");
		return -1;
	}

	for (i=(*start); i<argc; i++) {
		end = parse_option_end(argv[i]);
		if (!end)
			command_len=strlen(argv[i]);
		else {
			command_len=end-1;
			if (argv[i][end] == '=') {
				end++;
			}
		}

		if (!xstrncasecmp(argv[i], "Set", MAX(command_len, 3))) {
			i--;
			break;
		} else if (!end && !xstrncasecmp(argv[i], "WithDeleted",
						 MAX(command_len, 5))) {
			tres_cond->with_deleted = 1;
		} else if (!end && !xstrncasecmp(argv[i], "where",
						 MAX(command_len, 5))) {
			continue;
		} else if (!end
			  || !xstrncasecmp(argv[i], "Type",
					   MAX(command_len, 2))) {
			if (!tres_cond->type_list) {
				tres_cond->type_list =
					list_create(slurm_destroy_char);
			}
			if (slurm_addto_char_list(
				   tres_cond->type_list,
				   argv[i]+end))
				set = 1;
		} else if (!xstrncasecmp(argv[i], "Names",
					 MAX(command_len, 1))) {
			if (!tres_cond->name_list) {
				tres_cond->name_list =
					list_create(slurm_destroy_char);
			}
			if (slurm_addto_char_list(tres_cond->name_list,
						  argv[i]+end))
				set = 1;
		} else if (!xstrncasecmp(argv[i], "Format",
					 MAX(command_len, 1))) {
			if (format_list)
				slurm_addto_char_list(format_list, argv[i]+end);
		} else if (!xstrncasecmp(argv[i], "Ids",
					 MAX(command_len, 1))) {
			if (!tres_cond->id_list) {
				tres_cond->id_list =
					list_create(slurm_destroy_char);
			}
			if (slurm_addto_char_list(tres_cond->id_list,
						 argv[i]+end))
				set = 1;
		} else {
			exit_code=1;
			fprintf(stderr, " Unknown condition: %s\n"
				" Use keyword 'set' to modify value\n",
				argv[i]);
		}
	}

	(*start) = i;

	if (set)
		return 1;

	return 0;
}
示例#30
0
/*
 * scontrol_checkpoint - perform some checkpoint/resume operation
 * IN op - checkpoint operation
 * IN job_step_id_str - either a job name (for all steps of the given job) or
 *			a step name: "<jid>.<step_id>"
 * IN argc - argument count
 * IN argv - arguments of the operation
 * RET 0 if no slurm error, errno otherwise. parsing error prints
 *			error message and returns 0
 */
extern int scontrol_checkpoint(char *op,
			       char *job_step_id_str,
			       int argc,
			       char **argv)
{
	int rc = SLURM_SUCCESS;
	uint32_t job_id = 0, step_id = 0;
	char *next_str;
	uint32_t ckpt_errno;
	char *ckpt_strerror = NULL;
	int oplen = strlen(op);
	uint16_t max_wait = CKPT_WAIT, stick = 0;
	char *image_dir = NULL;

	if (job_step_id_str) {
		job_id = (uint32_t) strtol (job_step_id_str, &next_str, 10);
		if (next_str[0] == '.') {
			step_id = (uint32_t) strtol (&next_str[1], &next_str,
						     10);
		} else
			step_id = NO_VAL;
		if (next_str[0] != '\0') {
			fprintf(stderr, "Invalid job step name\n");
			return 0;
		}
	} else {
		fprintf(stderr, "Invalid job step name\n");
		return 0;
	}

	if (xstrncasecmp(op, "able", MAX(oplen, 1)) == 0) {
		time_t start_time;
		rc = slurm_checkpoint_able (job_id, step_id, &start_time);
		if (rc == SLURM_SUCCESS) {
			if (start_time) {
				char time_str[32];
				slurm_make_time_str(&start_time, time_str,
						    sizeof(time_str));
				printf("Began at %s\n", time_str);
			} else
				printf("Yes\n");
		} else if (slurm_get_errno() == ESLURM_DISABLED) {
			printf("No\n");
			rc = SLURM_SUCCESS;	/* not real error */
		}
	}
	else if (xstrncasecmp(op, "complete", MAX(oplen, 2)) == 0) {
		/* Undocumented option used for testing purposes */
		static uint32_t error_code = 1;
		char error_msg[64];
		sprintf(error_msg, "test error message %d", error_code);
		rc = slurm_checkpoint_complete(job_id, step_id, (time_t) 0,
			error_code++, error_msg);
	}
	else if (xstrncasecmp(op, "disable", MAX(oplen, 1)) == 0)
		rc = slurm_checkpoint_disable (job_id, step_id);
	else if (xstrncasecmp(op, "enable", MAX(oplen, 2)) == 0)
		rc = slurm_checkpoint_enable (job_id, step_id);
	else if (xstrncasecmp(op, "create", MAX(oplen, 2)) == 0) {
		if (_parse_checkpoint_args(argc, argv, &max_wait, &image_dir)){
			return 0;
		}
		rc = slurm_checkpoint_create (job_id, step_id, max_wait,
					      image_dir);

	} else if (xstrncasecmp(op, "requeue", MAX(oplen, 2)) == 0) {
		if (_parse_checkpoint_args(argc, argv, &max_wait, &image_dir)){
			return 0;
		}
		rc = slurm_checkpoint_requeue (job_id, max_wait, image_dir);

	} else if (xstrncasecmp(op, "vacate", MAX(oplen, 2)) == 0) {
		if (_parse_checkpoint_args(argc, argv, &max_wait, &image_dir)){
			return 0;
		}
		rc = slurm_checkpoint_vacate (job_id, step_id, max_wait,
					      image_dir);

	} else if (xstrncasecmp(op, "restart", MAX(oplen, 2)) == 0) {
		if (_parse_restart_args(argc, argv, &stick, &image_dir)) {
			return 0;
		}
		rc = slurm_checkpoint_restart (job_id, step_id, stick,
					       image_dir);

	} else if (xstrncasecmp(op, "error", MAX(oplen, 2)) == 0) {
		rc = slurm_checkpoint_error (job_id, step_id,
			&ckpt_errno, &ckpt_strerror);
		if (rc == SLURM_SUCCESS) {
			printf("error(%u): %s\n", ckpt_errno, ckpt_strerror);
			free(ckpt_strerror);
		}
	}

	else {
		fprintf (stderr, "Invalid checkpoint operation: %s\n", op);
		return 0;
	}

	return rc;
}