Exemple #1
0
/**
 * @brief get a line from a file pointed at by fp.  The line can be extended
 *	  onto the next line if it ends in a backslash (\).  If the string is
 *	  extended, the lines will be combined and the backslash will be
 *        stripped.
 *
 * @param[in] fp pointer to file to read from
 * @param[in, out] pbuf_size - pointer to size of buffer
 * @param[in, out] pbuf - pointer to buffer
 *
 * @return char *
 * @retval string read from file
 * @retval NULL - EOF or error
 * @par MT-Safe: no
 */
char *
pbs_fgets_extend(char **pbuf, int *pbuf_size, FILE *fp)
{
	static char *locbuf = NULL;
	static int locbuf_size = 0;
	char *buf;
	char *p;
	int len;

	if (pbuf == NULL || pbuf_size == NULL || fp == NULL)
		return NULL;

	if (locbuf == NULL) {
		if ((locbuf = malloc(PBS_FGETS_LINE_LEN)) == NULL)
			return NULL;
		locbuf_size = PBS_FGETS_LINE_LEN;
	}

	if (*pbuf_size == 0 || *pbuf == NULL) {
		if ((*pbuf = malloc(PBS_FGETS_LINE_LEN)) == NULL)
			return NULL;
		*pbuf_size = PBS_FGETS_LINE_LEN;
	}

	buf = *pbuf;
	locbuf[0] = '\0';
	buf[0] = '\0';

	while ((p = pbs_fgets(&locbuf, &locbuf_size, fp)) != NULL) {
		if (pbs_strcat(pbuf, pbuf_size, locbuf) == NULL)
			return NULL;

		buf = *pbuf;
		len = strlen(buf);

		/* we have two options:
		 * 1) We extend: string ends in a '\' and 0 or more whitespace
		 * 2) we do not extend: Not #1
		 * In the case of #1, we want the string to end just before the '\'
		 * In the case of #2 we want to leave the string alone.
		 */
		while (len > 0 && isspace(buf[len-1]))
			len--;

		if (len > 0) {
			if (buf[len - 1] != '\\') {
				break;
			}
			else {
				buf[len - 1] = '\0'; /* remove the backslash (\) */
			}
		}
	}

	/* if we read just EOF */
	if (p == NULL && buf[0] == '\0')
		return NULL;

	return buf;
}
Exemple #2
0
char *
pbs_fgets(char **pbuf, int *pbuf_size, FILE *fp)
{
	char fbuf[PBS_FGETS_LINE_LEN];
	char *buf;
	char *p;

	if (fp == NULL || pbuf == NULL || pbuf_size == NULL)
		return NULL;

	if (*pbuf_size == 0) {
		if ((*pbuf = malloc(PBS_FGETS_LINE_LEN)) == NULL)
			return NULL;
		*pbuf_size = PBS_FGETS_LINE_LEN;
	}
	buf = *pbuf;

	buf[0] = '\0';
	while ((p = fgets(fbuf, PBS_FGETS_LINE_LEN, fp)) != NULL) {
		buf = pbs_strcat(pbuf, pbuf_size, fbuf);
		if (buf == NULL)
			return NULL;

		if (buf[strlen(buf) - 1] == '\n') /* we've reached the end of the line */
			break;
	}
	if (p == NULL && buf[0] == '\0')
		return NULL;

	return *pbuf;
}
Exemple #3
0
/**
 * @brief
 * 		create a select from an nspec array to place chunks back on the
 *        same nodes as before
 *
 * @param[in]	nspec_array	-	npsec array to convert
 *
 * @return	converted select string
 */
char *
create_select_from_nspec(nspec **nspec_array)
{
	char *select_spec = NULL;
	int selsize = 0;
	char buf[1024];
	resource_req *req;
	int i;

	if (nspec_array == NULL || nspec_array[0] == NULL)
		return NULL;

	/* convert form (node:foo=X:bar=Y) into 1:vnode=node:foo=X:bay=Y*/
	for (i = 0; nspec_array[i] != NULL; i++) {
		/* Don't add exclhost chunks into our select. They will be added back when
		 * we call  eval_selspec() with the original place=exclhost.  If we added
		 * them, we'd have issues placing chunks w/o resources
		 */
		if (nspec_array[i]->resreq != NULL) {
			snprintf(buf, sizeof(buf), "1:vnode=%s", nspec_array[i]->ninfo->name);
			if (pbs_strcat(&select_spec, &selsize, buf) == NULL) {
				if (selsize > 0)
					free(select_spec);
				return NULL;
			}
			for (req = nspec_array[i]->resreq; req != NULL; req = req->next) {
				snprintf(buf, sizeof(buf), ":%s=%s", req->name, res_to_str(req, RF_REQUEST));
				if (pbs_strcat(&select_spec, &selsize, buf) == NULL) {
					if (selsize > 0)
						free(select_spec);
					return NULL;
				}
			}
			if (pbs_strcat(&select_spec, &selsize, "+") == NULL) {
				if (selsize > 0)
					free(select_spec);
				return NULL;
			}
		}
	}
	/* get rid of trailing '+' */
	select_spec[strlen(select_spec)-1] = '\0';

	return select_spec;
}
/**
 * @brief
 * 	validate_job_formula - validate that the sorting forumla is in the
 *	correct form.  We do this by calling python and having
 *	it catch exceptions.
 *
 */
int validate_job_formula(attribute *pattr, void *pobject, int actmode) {
	char *formula;
	char *errmsg = NULL;
	struct resource_def *pres;
	FILE *fp;
	char buf[1024];
	char pathbuf[MAXPATHLEN];
	char *globals1 = NULL;
	int globals_size1 = 1024;
	char *globals2 = NULL;
	int globals_size2 = 1024;
	char *script = NULL;
	int script_size = 2048;
	PyThreadState *ts_main = NULL;
	PyThreadState *ts_sub = NULL;
	int rc = 0;
	int err = 0;

	if (actmode == ATR_ACTION_FREE)
		return (0);

#ifndef PYTHON
	return PBSE_INTERNAL;
#else
	if (!Py_IsInitialized())
		return PBSE_INTERNAL;

	formula = pattr->at_val.at_str;
	if (formula == NULL)
		return PBSE_INTERNAL;

	globals1 = malloc(globals_size1);
	if(globals1 == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}

	globals2 = malloc(globals_size2);
	if(globals2 == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}

	strcpy(globals1, "globals1={");
	strcpy(globals2, "globals2={");

	/* We need to create a python dictionary to pass to python as a list
	 * of valid symbols.
	 */

	for (pres = svr_resc_def; pres; pres = pres->rs_next) {
		/* unknown resource is used as a delimiter between builtin and custom resources */
		if (strcmp(pres->rs_name, RESOURCE_UNKNOWN) != 0) {
			snprintf(buf, sizeof(buf), "\'%s\':1,", pres->rs_name);
			if(pbs_strcat(&globals1, &globals_size1, buf) == NULL) {
				rc = PBSE_SYSTEM;
				goto validate_job_formula_exit;
			}
			if (pres->rs_type == ATR_TYPE_LONG ||
				pres->rs_type == ATR_TYPE_SIZE ||
				pres->rs_type == ATR_TYPE_LL ||
				pres->rs_type == ATR_TYPE_SHORT ||
				pres->rs_type ==  ATR_TYPE_FLOAT) {
				if(pbs_strcat(&globals2, &globals_size2, buf) ==  NULL) {
					rc = PBSE_SYSTEM;
					goto validate_job_formula_exit;
				}
			}

		}
	}

	snprintf(buf, sizeof(buf), "\'%s\':1, '%s':1, \'%s\':1,\'%s\':1, \'%s\':1, \'%s\':1, \'%s\':1, \'%s\': 1}\n",
		FORMULA_ELIGIBLE_TIME, FORMULA_QUEUE_PRIO, FORMULA_JOB_PRIO,
		FORMULA_FSPERC, FORMULA_FSPERC_DEP, FORMULA_TREE_USAGE, FORMULA_FSFACTOR, FORMULA_ACCRUE_TYPE);
	if (pbs_strcat(&globals1, &globals_size1, buf) == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}
	if (pbs_strcat(&globals2, &globals_size2, buf) == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}

	/* Allocate a buffer for the Python code */
	script = malloc(script_size);
	if (script == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}
	*script = '\0';

	/* import math and initialize variables */
	sprintf(buf,
		"ans = 0\n"
		"errnum = 0\n"
		"errmsg = \'\'\n"
		"try:\n"
		"    from math import *\n"
		"except ImportError, e:\n"
		"    errnum=4\n"
		"    errmsg=str(e)\n");
	if (pbs_strcat(&script, &script_size, buf) == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}
	/* set up our globals dictionary */
	if (pbs_strcat(&script, &script_size, globals1) == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}
	if (pbs_strcat(&script, &script_size, globals2) == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}
	/* Now for the real guts: The initial try/except block*/
	sprintf(buf,
		"try:\n"
		"    exec(\'ans=");
	if (pbs_strcat(&script, &script_size, buf) == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}
	if (pbs_strcat(&script, &script_size, formula) == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}
	sprintf(buf, "\', globals1, locals())\n"
		"except SyntaxError, e:\n"
		"    errnum=1\n"
		"    errmsg=str(e)\n"
		"except NameError, e:\n"
		"    errnum=2\n"
		"    errmsg=str(e)\n"
		"except Exception, e:\n"
		"    pass\n"
		"if errnum == 0:\n"
		"    try:\n"
		"        exec(\'ans=");
	if (pbs_strcat(&script, &script_size, buf) == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}
	if (pbs_strcat(&script, &script_size, formula) == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}
	sprintf(buf, "\', globals2, locals())\n"
		"    except NameError, e:\n"
		"        errnum=3\n"
		"        errmsg=str(e)\n"
		"    except Exception, e:\n"
		"        pass\n");
	if (pbs_strcat(&script, &script_size, buf) == NULL) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}

	/* run the script in a subinterpreter */
	ts_main = PyThreadState_Get();
	ts_sub = Py_NewInterpreter();
	if (!ts_sub) {
		rc = PBSE_SYSTEM;
		goto validate_job_formula_exit;
	}
	err = PyRun_SimpleString(script);

	/* peek into the interpreter to get the values of err and errmsg */
	if (err == 0) {
		PyObject *module;
		PyObject *dict;
		PyObject *val;
		err = -1;
		if ((module = PyImport_AddModule("__main__"))) {
			if ((dict = PyModule_GetDict(module))) {
				char *p;
				if ((val = PyDict_GetItemString(dict, "errnum"))) {
					p = pbs_python_object_str(val);
					if (*p != '\0')
						err = atoi(p);
				}
				if ((val = PyDict_GetItemString(dict, "errmsg"))) {
					p = pbs_python_object_str(val);
					if (*p != '\0')
						errmsg = strdup(p);
				}
			}
		}
	}

	switch(err)
	{
		case 0: /* Success */
			rc = 0;
			break;
		case 1: /* Syntax error in formula */
			rc = PBSE_BAD_FORMULA;
			break;
		case 2: /* unknown resource name */
			rc = PBSE_BAD_FORMULA_KW;
			break;
		case 3: /* resource of non-numeric type */
			rc = PBSE_BAD_FORMULA_TYPE;
			break;
		case 4: /* import error */
			rc = PBSE_SYSTEM;
			break;
		default: /* unrecognized error */
			rc = PBSE_INTERNAL;
			break;
	}

	if (err == 0) {
		snprintf(pathbuf, sizeof(pathbuf), "%s/%s", pbs_conf.pbs_home_path,
			FORMULA_ATTR_PATH_SCHED);
		if ((fp = fopen(pathbuf, "w")) == NULL) {
			rc = PBSE_SYSTEM;
			goto validate_job_formula_exit;
		}

		fprintf(fp, "### PBS INTERNAL FILE DO NOT MODIFY ###\n");
		fprintf(fp, "%s\n", formula);

		fclose(fp);
	} else {
		snprintf(buf, sizeof(buf), "Validation Error: %s", errmsg?errmsg:"Internal error");
		log_event(PBSEVENT_DEBUG2, PBS_EVENTCLASS_SERVER, LOG_DEBUG, __func__, buf);
	}

validate_job_formula_exit:
	if (ts_main) {
		if (ts_sub)
			Py_EndInterpreter(ts_sub);
		PyThreadState_Swap(ts_main);
	}
	free(script);
	free(globals1);
	free(globals2);
	free(errmsg);
	return rc;
#endif
}