/** * @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; }
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; }
/** * @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 }