/****** uti/afsutil/sge_get_token_cmd() *************************************** * NAME * sge_get_token_cmd() -- Check if 'tokencmdname' is executable * * SYNOPSIS * int sge_get_token_cmd(const char *tokencmdname, char *buf, size_t lbuf) * * FUNCTION * Check if 'tokencmdname' exists and is executable. If an error * occures write a error message into 'buf' if not NULL. * Otherwise write error messages to stderr. * * INPUTS * const char *tokencmdname - command * char *buf - NULL or buffer for error message * size_t lbuf - size of buf * * NOTES * MT-NOTE: sge_get_token_cmd() is MT safe * * RESULT * int - error state * 0 - OK * 1 - Error ******************************************************************************/ int sge_get_token_cmd(const char *tokencmdname, char *buf, size_t lbuf) { SGE_STRUCT_STAT sb; if (!tokencmdname || !strlen(tokencmdname)) { if (!buf) { fprintf(stderr, "%s\n", MSG_COMMAND_NOPATHFORTOKEN); } else { sge_strlcpy(buf, MSG_COMMAND_NOPATHFORTOKEN, lbuf); } return 1; } if (SGE_STAT(tokencmdname, &sb) == -1) { if (!buf) { fprintf(stderr, MSG_COMMAND_NOFILESTATUS_S , tokencmdname); fprintf(stderr, "\n"); } else { snprintf(buf, lbuf, MSG_COMMAND_NOFILESTATUS_S , tokencmdname); } return 1; } if (!(sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) { if (!buf) { fprintf(stderr, MSG_COMMAND_NOTEXECUTABLE_S , tokencmdname); fprintf(stderr, "\n"); } else { snprintf(buf, lbuf, MSG_COMMAND_NOTEXECUTABLE_S , tokencmdname); } return 1; } return 0; }
/* look for an "sge" directory under a mount point of the cgroup */ static bool find_cgroup_dir(cgroup_t group, char *dir, size_t ldir) { FILE *fp; char path[2048], fstype[64], options[256]; bool ret = false, is_cpuset = (cg_cpuset == group); *dir = '\0'; if ((fp = fopen("/proc/self/mounts", "r")) == NULL) return ret; while (fscanf(fp, "%*s %2047s %63s %255s %*d %*d\n", path, fstype, options) == 3) { if (is_cpuset && strcmp(fstype, "cpuset") == 0) { ret = true; break; } else if ((strcmp(fstype, "cgroup") == 0)) { char *s = options, *tok, *save = NULL; bool rw = false, got_type = is_cpuset; while ((tok = strtok_r(s, ",", &save))) { if (strcmp(tok, "rw") == 0) rw = true; if (strcmp(tok, group_name[group]) == 0) got_type = true; if (rw && got_type) break; s = NULL; } sge_strlcat(path, "/sge", sizeof path); ret = rw && got_type && sge_is_directory(path); if (ret) break; } } fclose(fp); if (ret) sge_strlcpy(dir, path, ldir); return ret; }
/****** uti/hostname/sge_hostcpy() ******************************************** * NAME * sge_hostcpy() -- strcpy() for hostnames. * * SYNOPSIS * void sge_hostcpy(char *dst, const char *raw) * * FUNCTION * strcpy() for hostnames. Honours some configuration values: * - Domain name may be ignored * - Domain name may be replaced by a 'default domain' * - Hostnames may be used as they are. * - straight strcpy() for hostgroup names * * INPUTS * char *dst - possibly modified hostname * const char *raw - hostname * * SEE ALSO * uti/hostname/sge_hostcmp() * uti/hostname/sge_hostmatch() * * NOTES: * MT-NOTE: sge_hostcpy() is MT safe ******************************************************************************/ void sge_hostcpy(char *dst, const char *raw) { bool ignore_fqdn = bootstrap_get_ignore_fqdn(); bool is_hgrp = is_hgroup_name(raw); const char *default_domain; if (dst == NULL || raw == NULL) { return; } if (is_hgrp) { /* hostgroup name: not in FQDN format, copy the entire string*/ sge_strlcpy(dst, raw, CL_MAXHOSTLEN); return; } if (ignore_fqdn) { char *s = NULL; /* standard: simply ignore FQDN */ sge_strlcpy(dst, raw, CL_MAXHOSTLEN); if ((s = strchr(dst, '.'))) { *s = '\0'; } return; } if ((default_domain = bootstrap_get_default_domain()) != NULL && SGE_STRCASECMP(default_domain, "none") != 0) { /* exotic: honour FQDN but use default_domain */ if (!strchr(raw, '.')) { snprintf(dst, CL_MAXHOSTLEN, "%s.%s", raw, default_domain); } else { sge_strlcpy(dst, raw, CL_MAXHOSTLEN); } } else { /* hardcore: honour FQDN, don't use default_domain */ sge_strlcpy(dst, raw, CL_MAXHOSTLEN); } return; }
/*----------------------------------------------------------------- * check_if_valid_shadow * return 0 if we are a valid shadow * -1 if not * -2 if lock file exits or master was running on same machine *-----------------------------------------------------------------*/ static int check_if_valid_shadow(char *binpath, char *oldqmaster, const char *act_qmaster_file, const char *shadow_master_file, const char *qualified_hostname, const char *binary_path) { struct hostent *hp; DENTER(TOP_LAYER, "check_if_valid_shadow"); if (isLocked(QMASTER_LOCK_FILE)) { DPRINTF(("lock file exits\n")); DRETURN(-2); } /* we can't read act_qmaster file */ if (get_qm_name(oldqmaster, act_qmaster_file, NULL)) { WARNING((SGE_EVENT, MSG_SHADOWD_CANTREADACTQMASTERFILEX_S, act_qmaster_file)); DRETURN(-1); } /* we can't resolve hostname of old qmaster */ hp = sge_gethostbyname_retry(oldqmaster); if (hp == (struct hostent *) NULL) { WARNING((SGE_EVENT, MSG_SHADOWD_CANTRESOLVEHOSTNAMEFROMACTQMASTERFILE_SS, act_qmaster_file, oldqmaster)); DRETURN(-1); } /* we are on the same machine as old qmaster */ if (!strcmp(hp->h_name, qualified_hostname)) { sge_free_hostent(&hp); DPRINTF(("qmaster was running on same machine\n")); DRETURN(-2); } sge_free_hostent(&hp); /* we are not in the shadow master file */ if (host_in_file(qualified_hostname, shadow_master_file)) { WARNING((SGE_EVENT, MSG_SHADOWD_NOTASHADOWMASTERFILE_S, shadow_master_file)); DRETURN(-1); } sge_strlcpy(binpath, binary_path, SGE_PATH_MAX); /* copy global configuration path */ DPRINTF((""SFQ"\n", binpath)); DPRINTF(("we are a candidate for shadow master\n")); DRETURN(0); }
/****** uti/prog/sge_get_root_dir() ******************************************* * NAME * sge_get_root_dir() -- SGE/SGEEE installation directory * * SYNOPSIS * const char* sge_get_root_dir(int do_exit, * char *buffer, * size_t size, * int do_error_log ) * * FUNCTION * This function returns the installation directory of SGE/SGEEE. * This directory is defined by the SGE_ROOT environment variable * of the calling process. * If the environment variable does not exist or is not set then * this function will handle this as error and return NULL * (do_exit = 0). If 'do_exit' is 1 and an error occures, the * function will terminate the calling application. * * INPUTS * int do_exit - Terminate the application in case of an error * char *buffer - buffer to be used for error message * size_t size - size of buffer * int do_error_log - enable/disable error logging * * RESULT * const char* - Root directory of the SGE/SGEEE installation * * NOTES * MT-NOTE: sge_get_arch() is MT safe *******************************************************************************/ const char *sge_get_root_dir(int do_exit, char *buffer, size_t size, int do_error_log) { char *sge_root; char *s; DENTER_(TOP_LAYER, "sge_get_root_dir"); /* * Read some env variables */ sge_root = getenv("SGE_ROOT"); /* * Check the env variables */ if (sge_root) { s = sge_root; } else { goto error; } if (!s || strlen(s)==0) { goto error; } else { /* * Get rid of trailing slash */ if (s[strlen(s)-1] == '/') { s[strlen(s)-1] = '\0'; } } DRETURN_(s); error: if (do_error_log) { if (buffer != NULL) { sge_strlcpy(buffer, MSG_SGEROOTNOTSET, size); } else { CRITICAL((SGE_EVENT, MSG_SGEROOTNOTSET)); } } DEXIT_; if (do_exit) { SGE_EXIT(NULL, 1); } return NULL; }
void sge_err_get(sge_err_t *id, char *message, size_t size) { DENTER(ERR_LAYER, "sge_err_get"); if (id != NULL && message != NULL && size > 0) { sge_err_object_t *err_obj = NULL; sge_err_get_object(&err_obj); if (err_obj->id != SGE_ERR_SUCCESS) { *id = err_obj->id; sge_strlcpy(message, err_obj->message, size); } else { *id = SGE_ERR_SUCCESS; message[0] = '\0'; } } DEXIT; }
/* Copy the controller CFILE file contents from the parent into DIR, e.g. to populate "cpus". */ static bool copy_from_parent(char *dir, const char *cfile) { char parent_path[SGE_PATH_MAX], path[SGE_PATH_MAX], dirx[SGE_PATH_MAX]; char *prefix = ""; /* For some reason we're not getting the glibc version of dirname that doesn't alter its arg. */ sge_strlcpy(dirx, dir, sizeof dirx); if (strncmp(dir, cgroup_dir(cg_cpuset), strlen(cgroup_dir(cg_cpuset))) && cpuset_prefix && strncmp("cpuset.", cfile, 7) != 0) prefix = "cpuset."; snprintf(path, sizeof path, "%s/%s%s", dir, prefix, cfile); snprintf(parent_path, sizeof parent_path, "%s/%s%s", dirname(dirx), prefix, cfile); return sge_copy_append(parent_path, path, SGE_MODE_COPY) ? false : true; }
int schedd_log_list(lList **monitor_alpp, bool monitor_next_run, const char *logstr, lList *lp, int nm) { int fields[] = { 0, 0 }; const char *delis[] = {NULL, " ", NULL}; lList *lp_part = NULL; lListElem *ep = NULL; DENTER(TOP_LAYER, "schedd_log_list"); #ifndef WIN32NATIVE if (monitor_alpp == NULL && !monitor_next_run) { DRETURN(0); } fields[0] = nm; for_each(ep, lp) { if (!lp_part) { lp_part = lCreateList("partial list", lGetListDescr(lp)); } lAppendElem(lp_part, lCopyElem(ep)); if ((lGetNumberOfElem(lp_part) == NUM_ITEMS_ON_LINE) || !lNext(ep)) { char log_string[2048]; sge_strlcpy(log_string, logstr, sizeof(log_string)); #ifndef WIN32NATIVE uni_print_list(NULL, log_string + strlen(log_string), sizeof(log_string) - strlen(log_string) - 1, lp_part, fields, delis, 0); #endif schedd_log(log_string, monitor_alpp, monitor_next_run); lFreeList(&lp_part); lp_part = NULL; } } #else DPRINTF(("schedd_log_list does nothing for QMonNT !!!\n")); #endif DEXIT; return 0; }
/****** uti/afsutil/sge_afs_extend_token() ************************************ * NAME * sge_afs_extend_token() -- Extend an AFS token * * SYNOPSIS * int sge_afs_extend_token(const char *command, char *tokenbuf, * const char *user, int token_extend_time, * char *err_str, size_t lstr) * * FUNCTION * Call 'command', pipe content of 'tokenbuf' to 'command', using * 'user' as arg1 and 'token_extend_time' as arg2 * * INPUTS * const char *command - command * char *tokenbuf - input for command * const char *user - 1st argument for command * int token_extend_time - 2nd argument for command * char *err_str - error message * size_t lstr - length of err_str * * NOTES * MT-NOTE: sge_afs_extend_token() is not MT safe because it uses MT unsafe * MT-NOTE: sge_peopen() * * RESULT * int - error state * 0 - OK * -1 - Error ******************************************************************************/ int sge_afs_extend_token(const char *command, char *tokenbuf, const char *user, int token_extend_time, char *err_str, size_t lstr) { pid_t command_pid; FILE *fp_in, *fp_out, *fp_err; int ret; char cmdbuf[SGE_PATH_MAX+128]; DENTER(TOP_LAYER, "sge_afs_extend_token"); snprintf(cmdbuf, sizeof(cmdbuf), "%s %s %d", command, user, token_extend_time); if (err_str) { sge_strlcpy(err_str, cmdbuf, lstr); } command_pid = sge_peopen("/bin/sh", 0, cmdbuf, NULL, NULL, &fp_in, &fp_out, &fp_err, false); if (command_pid == -1) { if (err_str) { snprintf(err_str, lstr, MSG_TOKEN_NOSTART_S , cmdbuf); } DEXIT; return -1; } if (sge_string2bin(fp_in, tokenbuf) == -1) { if (err_str) { snprintf(err_str, lstr, MSG_TOKEN_NOWRITEAFS_S , cmdbuf); } DEXIT; return -1; } if ((ret = sge_peclose(command_pid, fp_in, fp_out, fp_err, NULL)) != 0) { if (err_str) { snprintf(err_str, lstr, MSG_TOKEN_NOSETAFS_SI , cmdbuf, ret); } DEXIT; return -1; } return 0; }
/*-------------------------------------------------------------------------*/ static void qmonSchedTime(Widget w, XtPointer cld, XtPointer cad) { Widget input_field = (Widget) cld; char stringval[256]; Boolean status = False; String current; DENTER(GUI_LAYER, "qmonSchedTime"); current = XmtInputFieldGetString(input_field); sge_strlcpy(stringval, current ? current : "", sizeof(stringval)); status = XmtAskForTime(w, NULL, "@{Enter time}", stringval, sizeof(stringval), NULL, False); if (stringval[0] == '\0') status = False; if (status) XmtInputFieldSetString(input_field, stringval); DEXIT; }
/****** uti/sge_tmpnam/sge_tmpnam() ******************************************* * NAME * sge_tmpnam() -- Secure replacement for tmpnam() * * SYNOPSIS * char* sge_tmpnam(char *aBuffer) * * FUNCTION * Generate a string that is a unique valid filename within a given * directory. The corresponding file is created as soon as the filename * has been generated, thus avoiding any delay between filename generation * and actual file usage. The file will have read and write access for the * user only. * * The 'aBuffer' argument points to an array of at least SGE_PATH_MAX length. * 'aBuffer' will contain the generated filename upon successful completion. * In addition, 'aBuffer' will be returned. If the function fails, NULL will * be returned and 'errno' set to indicate the error. * * If the environment variable TMPDIR is defined, it's value will be used * as the path prefix for the file. If TMPDIR is not set or it does not * refer to a valid directory, the value of P_tmpdir will be used. * P_tmpdir shall be defined in <stdio.h>. If P_tmpdir is not defined or * it does not refer to a valid directory, /tmp will be used. * * NOTE: Since the file already exists, the O_EXCL flag must not be used if * the returned filename is opened for usage within an application. It is, * however, the duty of the application calling this function to delete the * file denoted by the generated filename after it is no longer needed. * * INPUTS * char *aBuffer - Array to hold filename * * RESULT * char* - Points to 'aBuffer' if successful, NULL otherwise * * NOTE * MT-NOTE: sge_tmpnam() is MT safe. ******************************************************************************/ char *sge_tmpnam(char *aBuffer, dstring *error_message) { dstring s = DSTRING_INIT; DENTER(TOP_LAYER, "sge_tmpnam"); if (aBuffer == NULL) { sge_dstring_sprintf(error_message, MSG_TMPNAM_GOT_NULL_PARAMETER); DEXIT; return NULL; } if (elect_path(&s) < 0) { sge_dstring_sprintf(error_message, MSG_TMPNAM_CANNOT_GET_TMP_PATH); sge_dstring_free(&s); DEXIT; return NULL; } if ((sge_dstring_get_string(&s))[sge_dstring_strlen(&s)-1] != '/') { sge_dstring_append_char(&s, '/'); } if (spawn_file(&s, error_message) < 0) { sge_dstring_free(&s); DEXIT; return NULL; } sge_strlcpy(aBuffer, sge_dstring_get_string(&s), SGE_PATH_MAX); sge_dstring_free(&s); DPRINTF(("sge_tmpnam: returning %s\n", aBuffer)); DEXIT; return aBuffer; }
/* MT-NOTE: extended_parse_ulong_val() is MT safe */ int extended_parse_ulong_val(double *dvalp, u_long32 *uvalp, u_long32 type, const char *s, char *error_str, int error_len, int enable_infinity, bool only_positive) { int retval = 0; /* error */ char dummy[10]; u_long32 dummy_uval; if (s == NULL) { return 0; } if (only_positive && (strchr(s, '-') != NULL)) { if (error_str) { sge_strlcpy(error_str, MSG_GDI_NUMERICALVALUENOTPOSITIVE, error_len); } return 0; } if ((enable_infinity == 0) && (strcasecmp(s,"infinity") == 0)) { if (error_str) { sge_strlcpy(error_str, MSG_GDI_VALUETHATCANBESETTOINF, error_len); } return 0; } if (uvalp == NULL) { uvalp = &dummy_uval; } /* here we have to convert from string representation of the request value into an ulong value */ switch (type) { case TYPE_LOG: retval = sge_parse_loglevel_val(uvalp, s); if (retval != 1) { if (error_str != NULL) { sge_strlcpy(error_str, "loglevel value", error_len); } } break; case TYPE_INT: case TYPE_TIM: case TYPE_MEM: case TYPE_BOO: case TYPE_DOUBLE: /* dirty but isolated .. */ if (error_str != NULL) { *uvalp = sge_parse_num_val(NULL, dvalp, s, s, error_str, error_len); if (!error_str[0]) /* err msg written ? */ retval = 1; /* no error */ else { if (type==TYPE_INT) sge_strlcpy(error_str, "integer value", error_len); else if (type==TYPE_TIM) sge_strlcpy(error_str, "time value", error_len); else if (type==TYPE_BOO) sge_strlcpy(error_str, "boolean value", error_len); else if (type==TYPE_DOUBLE) sge_strlcpy(error_str, "double value", error_len); else sge_strlcpy(error_str, "memory value", error_len); } } else { dummy[0] = '\0'; *uvalp = sge_parse_num_val(NULL, dvalp, s, s, dummy, sizeof(dummy)); if (!dummy[0]) { /* err msg written ? */ retval = 1; /* no error */ } } break; default: break; } return retval; }
/*-------------------------------------------------------------------------*/ static Boolean qmonSchedSet(lListElem *sep) { static char schedd_job_info[BUFSIZ]; DENTER(GUI_LAYER, "qmonSchedSet"); if (!sep) { DRETURN(False); } /* printf("------> qmonSchedSet\n"); */ /* lWriteElemTo(sep, stdout); */ data.algorithm = sge_strdup(data.algorithm, (StringConst)lGetString(sep, SC_algorithm)); data.schedule_interval = sge_strdup(data.schedule_interval, (StringConst)lGetString(sep, SC_schedule_interval)); data.sc_params = sge_strdup(data.sc_params, (StringConst)lGetString(sep, SC_params)); data.maxujobs = lGetUlong(sep, SC_maxujobs); data.flush_submit_secs = lGetUlong(sep, SC_flush_submit_sec); data.flush_finish_secs = lGetUlong(sep, SC_flush_finish_sec); data.max_reservation = lGetUlong(sep, SC_max_reservation); /* this depends on the kind queue_sort_method is represented */ data.queue_sort_method = lGetUlong(sep, SC_queue_sort_method); /* ** load adjustments need special treatment */ data.job_load_adjustments = lCopyList("copy", lGetList(sep, SC_job_load_adjustments)); data.load_adjustment_decay_time = sge_strdup(data.load_adjustment_decay_time, (StringConst)lGetString(sep, SC_load_adjustment_decay_time)); data.load_formula = sge_strdup(data.load_formula, (StringConst)lGetString(sep, SC_load_formula)); data.reprioritize_interval = sge_strdup(data.reprioritize_interval, (StringConst)lGetString(sep, SC_reprioritize_interval)); data.default_duration = sge_strdup(data.default_duration, (StringConst)lGetString(sep, SC_default_duration)); /** printf("->data.algorithm: '%s'\n", data.algorithm ? data.algorithm : "-NA-"); printf("->data.schedule_interval: '%s'\n", data.schedule_interval ? data.schedule_interval : "-NA-"); printf("->data.sc_params: '%s'\n", data.sc_params ? data.sc_params : "-NA-"); printf("->data.maxujobs: '%d'\n", data.maxujobs ); printf("->data.flush_submit_secs: '%d'\n", data.flush_submit_secs ); printf("->data.flush_finish_secs: '%d'\n", data.flush_finish_secs ); printf("->data.max_reservation: '%d'\n", data.max_reservation ); printf("->data.queue_sort_method: '%d'\n", data.queue_sort_method ); printf("->data.load_adjustment_decay_time: '%s'\n", data.load_adjustment_decay_time ? data.load_adjustment_decay_time : "-NA-"); printf("->data.load_formula: '%s'\n", data.load_formula ? data.load_formula : "-NA-"); **/ /* ** set the dialog values */ XmtDialogSetDialogValues(qmon_sconf, (XtPointer) &data); /* ** schedd_job_info needs some extras ** attention: order must match order of labels in qmon_sconf.ad ** ** Qmon*sconf_general*sconf_job_info.chooserType: ChooserOption ** Qmon*sconf_general*sconf_job_info.strings: \ ** "False", \ ** "True", \ ** "Job Range" */ if (lGetString(sep, SC_schedd_job_info)) sge_strlcpy(schedd_job_info, lGetString(sep, SC_schedd_job_info), BUFSIZ); else strcpy(schedd_job_info, "false"); if (!strcasecmp(schedd_job_info, "false")) { XmtChooserSetState(sconf_job_info, 0, True); XmtInputFieldSetString(sconf_job_range, ""); } else if (!strcasecmp(schedd_job_info, "true")) { XmtChooserSetState(sconf_job_info, 1, True); XmtInputFieldSetString(sconf_job_range, ""); } else { char *sji; strtok(schedd_job_info, " \t"); sji = strtok(NULL, "\n"); XmtChooserSetState(sconf_job_info, 2, True); XmtInputFieldSetString(sconf_job_range, sji); } qmonSchedFreeData(); DRETURN(True); }
/*----------------------------------------------------------------------- * Read name of qmaster from master_file * -> master_file * <- return -1 error in err_str * 0 host name of master in master_host * don't copy error to err_str if err_str = NULL * master_file name of file which should point to act_qmaster file * copy name of qmaster host to master_host * * NOTES * MT-NOTE: get_qm_name() is MT safe *-----------------------------------------------------------------------*/ int get_qm_name( char *master_host, const char *master_file, char *err_str, size_t elen ) { FILE *fp; char buf[CL_MAXHOSTLEN*3+1], *cp, *first; int len; DENTER(TOP_LAYER, "get_qm_name"); if (!master_host || !master_file) { if (err_str) { if (master_host) { snprintf(err_str, elen, SFNMAX, MSG_GDI_NULLPOINTERPASSED); } } DRETURN(-1); } if (!(fp=fopen(master_file,"r"))) { ERROR((SGE_EVENT, MSG_GDI_FOPEN_FAILED, master_file, strerror(errno))); if (err_str) { snprintf(err_str, elen, MSG_GDI_OPENMASTERFILEFAILED_S, master_file); } DRETURN(-1); } /* read file in one sweep and append O Byte to the end */ if (!(len = fread(buf, 1, CL_MAXHOSTLEN*3, fp))) { if (err_str) { snprintf(err_str, elen, MSG_GDI_READMASTERHOSTNAMEFAILED_S, master_file); } } buf[len] = '\0'; /* Skip white space including newlines */ cp = buf; while (*cp && (*cp == ' ' || *cp == '\t' || *cp == '\n')) cp++; first = cp; /* read all non white space characters */ while (*cp && !(*cp == ' ' || *cp == '\t' || *cp == '\n')) { cp++; } *cp = '\0'; len = cp - first; if (len == 0) { if (err_str) { snprintf(err_str, elen, MSG_GDI_MASTERHOSTNAMEHASZEROLENGTH_S, master_file); } FCLOSE(fp); DRETURN(-1); } if (len > CL_MAXHOSTLEN - 1) { if (err_str) { snprintf(err_str, elen, MSG_GDI_MASTERHOSTNAMEEXCEEDSCHARS_SI, master_file, (int) CL_MAXHOSTLEN); snprintf(err_str, elen, "\n"); } FCLOSE(fp); DRETURN(-1); } FCLOSE(fp); sge_strlcpy(master_host, first, CL_MAXHOSTLEN); DRETURN(0); FCLOSE_ERROR: DRETURN(-1); }
/****** err_trace/shepherd_trace_init_intern() ******************************* * NAME * shepherd_trace_init_intern() -- Initialize shepherd's tracing. * * SYNOPSIS * static FILE* shepherd_trace_init(char *trace_file_path, * char *trace_file_name) * * FUNCTION * Opens the shepherd's trace file and sets the FD_CLOEXEC-flag so it will * be closed automatically in an exec()-call. * Must be called with euid=admin user to work properly! * * INPUTS * char *trace_file_path - either the whole path of the trace file (including * the file itself) * or NULL to retrieve the file pointer of an already * opened trace file. * char *trace_file_name - the name of the trace file itself. Ignored when * *trace_file_path is NULL. * * RESULT * FILE* - If successfully opened, the file pointer of shepherd's trace file. * - Otherwise NULL. *******************************************************************************/ static FILE* shepherd_trace_init_intern(st_shepherd_file_t shepherd_file) { static char path[SGE_PATH_MAX]; static bool called = false; SGE_STRUCT_STAT statbuf; dstring ds; char buffer[SGE_PATH_MAX+128]; char tmppath[SGE_PATH_MAX]; int fd = -1; FILE *fp = NULL; int do_chown = 0; /* * after changing into the jobs cwd we need an * absolute path to the error/trace file */ if (called == false) { getcwd(path, sizeof(path)); called=true; } snprintf(tmppath, SGE_PATH_MAX,"%s/%s",path, g_shepherd_file_name[shepherd_file]); sge_strlcpy(g_shepherd_file_path[shepherd_file], tmppath, SGE_PATH_MAX); /* If the file does not exist, create it. Otherwise just open it. */ if (SGE_STAT(tmppath, &statbuf)) { fd = SGE_OPEN3(tmppath, O_RDWR | O_CREAT | O_APPEND, 0644); if (fd<0) { sge_dstring_init(&ds, buffer, sizeof(buffer)); sge_dstring_sprintf(&ds, "creat(%s) failed: %s", tmppath, strerror(errno)); shepherd_panic(buffer); } if (getuid() == SGE_SUPERUSER_UID) { /* We must give the file to the job owner later */ do_chown = 1; } else { /* We are not root, so we have to own all files anyway. */ do_chown = 0; } } else { /* The file already exists. We get here when * a) a exec() failed or * b) after the execution of prolog/job, when the job/epilog * tries to init the error/exit status files. * * In a root system we can just open the file, because we are either * root or the job user who owns the file. * In a admin user system we must set our euid to root to open it, then * it is the same as the root system. * In a test user system we are the owner of the file and can open it. * * When we are root (masked or not), we gave this file to the * prolog user/job user right after its creation. But we can have * 3 different users for prolog, job and epilog, so we must give * the file here to the next user. * This must be done via shepherd_trace_chown() in the shepherd * before we switch to this user there. * It can't be done here because we don't know if we are in * case a) (exec failed) or case b) (after execution of prolog/job). */ int old_euid = SGE_SUPERUSER_UID; /* * Work around for CR 6293411: * See shepherd_trace_exit() for details. */ if (getuid() == SGE_SUPERUSER_UID) { old_euid = geteuid(); seteuid(SGE_SUPERUSER_UID); } fd = SGE_OPEN2(tmppath, O_RDWR | O_APPEND); if (fd<0) { sge_dstring_init(&ds, buffer, sizeof(buffer)); sge_dstring_sprintf(&ds, "open(%s) failed: %s", tmppath, strerror(errno)); shepherd_panic(buffer); } do_chown = 0; /* * Switch back to admin user? */ if (old_euid != SGE_SUPERUSER_UID) { seteuid(old_euid); } } /* Something went wrong. */ if (fd<0) { return NULL; } /* To avoid to block stdin, stdout or stderr, dup the fd until it is >= 3 */ if (fd<3) { dup_fd(&fd); } /* Set FD_CLOEXEC flag to automatically close the file in an exec() */ if (!set_cloexec(fd)) { shepherd_panic("set_cloexec() failed"); return NULL; } /* * Now open a FILE* from the file descriptor, so we can use fprintf(). */ fp = fdopen(fd, "a"); if (!fp) { sge_dstring_init(&ds, buffer, sizeof(buffer)); sge_dstring_sprintf(&ds, "can't open %s file \"%s\": %s\n", g_shepherd_file_name[shepherd_file], tmppath, strerror(errno)); shepherd_panic(buffer); return NULL; } if (do_chown && strlen(g_job_owner) > 0) { shepherd_trace_chown_intern(g_job_owner, fp, shepherd_file); } return fp; }
/*-------------------------------------------------------------------------*/ static void set_StringList( Widget w, XtPointer address, XrmQuark type, Cardinal size ) { lList *lp = NULL; Widget parent; /* * Here special Qmon Quarks are used. Does it work ? */ if (type != QmonQUS_Type && type != QmonQMR_Type && type != QmonQPR_Type && type != QmonQSTR_Type && type != QmonQSTU_Type && type != QmonQHR_Type) { XmtWarningMsg("XmtDialogSetDialogValues", "XbaeMatrix", "Type Mismatch: Widget '%s':\n\tCan't set widget values" " from a resource of type '%s'", XtName(w), XrmQuarkToString(type)); return; } if (size == sizeof(lList*)) lp = *(lList**) address; else return; /* if our parent is a layout widget disable/reenable it */ parent = XtParent(w); while (parent && !XtIsSubclass(parent, xmtLayoutWidgetClass)) parent = XtParent(parent); XmtLayoutDisableLayout(parent); if (type == QmonQUS_Type) { UpdateXmListFromCull(w, XmFONTLIST_DEFAULT_TAG, lp, US_name); } if (type == QmonQPR_Type) { UpdateXmListFromCull(w, XmFONTLIST_DEFAULT_TAG, lp, PR_name); } if (type == QmonQHR_Type) { UpdateXmListFromCull(w, XmFONTLIST_DEFAULT_TAG, lp, HR_name); } if (type == QmonQMR_Type) { String *str_table = NULL; Cardinal itemCount; StringConst str1, str2; int size, i; char buf[BUFSIZ]; lListElem *ep = NULL; XtVaGetValues(w, XmNitemCount, &itemCount, NULL); if (!lp) { if (itemCount) XmListDeleteAllItems(w); return; } if ((size = lGetNumberOfElem(lp)) <=0) { return; } if (!(str_table = (String *)XtMalloc(sizeof(String)*size))) { return; } for (ep=lFirst(lp), i=0; ep; ep=lNext(ep), i++) { str1 = (StringConst)lGetString(ep, MR_user); str2 = (StringConst)lGetHost(ep, MR_host); if (str1) { if (!str2) sge_strlcpy(buf, str1, BUFSIZ); else snprintf(buf, BUFSIZ, "%s@%s", str1, str2); str_table[i] = XtNewString(buf); } else str_table[i] = NULL; } UpdateXmList(w, str_table, size, XmFONTLIST_DEFAULT_TAG); StringTableFree(str_table, size); } if (type == QmonQSTR_Type) { UpdateXmListFromCull(w, XmFONTLIST_DEFAULT_TAG, lp, ST_name); } if (type == QmonQSTU_Type) { UpdateXmListFromCull(w, XmFONTLIST_DEFAULT_TAG, lp, STU_name); } XmtLayoutEnableLayout(parent); }
/****** sge_select_queue/get_attribute() *************************************** * NAME * get_attribute() -- looks for an attribut, but only for one level (for host, global, or queue) * * SYNOPSIS * static lListElem* get_attribute(const char *attrname, lList *config_attr, * lList *actual_attr, lList *load_attr, lList *centry_list, lListElem * *queue, lListElem *rep, u_long32 layer, double lc_factor, dstring *reason) * * FUNCTION * Extracts the attribut specified with 'attrname' and finds the * more important one, if it is defined multiple times on the same * level. It only cares about one level. * If the attribute is a consumable, one can specify a point in time and a duration. * This will get the caller the min amount of that resource during the time frame. * * INPUTS * const char *attrname - attribute name one is looking for * lList *config_attr - user defined attributes (CE_Type) * lList *actual_attr - current usage of consumables (RUE_Type) * lList *load_attr - load attributes * lList *centry_list - the system wide attribute configuration * lListElem *queue - the current queue, or null, if one works on hosts * u_long32 layer - the current layer * double lc_factor - the load correction value * dstring *reason - space for error messages or NULL * bool zero_utilization - ??? * u_long32 start_time - begin of the time interval, one asks for the resource * u_long32 duration - the duration the interval * * RESULT * static lListElem* - the element one was looking for or NULL * *******************************************************************************/ lListElem* get_attribute(const char *attrname, lList *config_attr, lList *actual_attr, lList *load_attr, const lList *centry_list, lListElem *queue, u_long32 layer, double lc_factor, dstring *reason, bool zero_utilization, u_long32 start_time, u_long32 duration) { lListElem *actual_el=NULL; lListElem *load_el=NULL; lListElem *cplx_el=NULL; DENTER(BASIS_LAYER, "get_attribute"); /* resource_attr is a complex_entry (CE_Type) */ if (config_attr) { lListElem *temp = lGetElemStr(config_attr, CE_name, attrname); if (temp){ cplx_el = lCopyElem(lGetElemStr(centry_list, CE_name, attrname)); if(!cplx_el){ /* error */ DRETURN(NULL); } lSetUlong(cplx_el, CE_dominant, layer | DOMINANT_TYPE_FIXED); lSetUlong(cplx_el, CE_pj_dominant, DOMINANT_TYPE_VALUE); /* default, no value set */ lSetDouble(cplx_el, CE_doubleval, lGetDouble(temp,CE_doubleval) ); lSetString(cplx_el, CE_stringval, lGetString(temp,CE_stringval) ); } } if (cplx_el && lGetUlong(cplx_el, CE_consumable) != CONSUMABLE_NO) { lSetUlong(cplx_el, CE_pj_dominant, layer | DOMINANT_TYPE_CONSUMABLE); lSetUlong(cplx_el, CE_dominant, DOMINANT_TYPE_VALUE); /* treat also consumables as fixed attributes when assuming an empty queuing system */ if (sconf_get_qs_state() == QS_STATE_FULL) { if (actual_attr && (actual_el = lGetElemStr(actual_attr, RUE_name, attrname))){ dstring ds; char as_str[20]; double utilized = zero_utilization ? 0 : utilization_max(actual_el, start_time, duration, false); switch (lGetUlong(cplx_el, CE_relop)) { case CMPLXGE_OP: case CMPLXGT_OP: lSetDouble(cplx_el, CE_pj_doubleval, utilized); break; case CMPLXEQ_OP: case CMPLXLT_OP: case CMPLXLE_OP: case CMPLXNE_OP: default: lSetDouble(cplx_el, CE_pj_doubleval, lGetDouble(cplx_el, CE_doubleval) - utilized); break; } sge_dstring_init(&ds, as_str, sizeof(as_str)); sge_dstring_sprintf(&ds, "%8.3f", (float)lGetDouble(cplx_el, CE_pj_doubleval)); lSetString(cplx_el,CE_pj_stringval, as_str); } else{ sge_dstring_sprintf(reason, MSG_ATTRIB_ACTUALELEMENTTOATTRIBXMISSING_S, attrname); lFreeElem(&cplx_el); DRETURN(NULL); } } else{ lSetDouble(cplx_el, CE_pj_doubleval, lGetDouble(cplx_el, CE_doubleval)); lSetString(cplx_el,CE_pj_stringval, lGetString(cplx_el, CE_stringval)); } } /** check for a load value */ if (load_attr && (load_el = lGetElemStr(load_attr, HL_name, attrname)) && (sconf_get_qs_state()==QS_STATE_FULL || lGetBool(load_el, HL_static)) && (!is_attr_prior(cplx_el, cplx_el))) { lListElem *ep_nproc=NULL; int nproc=1; if (!cplx_el){ cplx_el = lCopyElem(lGetElemStr(centry_list, CE_name, attrname)); if (!cplx_el){ /* error */ DRETURN(NULL); } lSetUlong(cplx_el, CE_dominant, DOMINANT_TYPE_VALUE); lSetUlong(cplx_el, CE_pj_dominant, DOMINANT_TYPE_VALUE); } if ((ep_nproc = lGetElemStr(load_attr, HL_name, LOAD_ATTR_NUM_PROC))) { const char *cp = lGetString(ep_nproc, HL_value); if (cp) nproc = MAX(1, atoi(lGetString(ep_nproc, HL_value))); } { const char *load_value=NULL; u_long32 type; double dval; load_value = lGetString(load_el, HL_value); /* are we working on string values? if though, than it is easy */ if ( (type = lGetUlong(cplx_el, CE_valtype)) == TYPE_STR || type == TYPE_CSTR || type == TYPE_HOST || type == TYPE_RESTR) { lSetString(cplx_el, CE_stringval, load_value); lSetUlong(cplx_el, CE_dominant, layer | DOMINANT_TYPE_LOAD); } else { /* working on numerical values */ lListElem *job_load; char err_str[256]; char sval[100]; u_long32 dom_type = DOMINANT_TYPE_LOAD; lList *load_adjustments = sconf_get_job_load_adjustments(); job_load=lGetElemStr(load_adjustments, CE_name, attrname); if (parse_ulong_val(&dval, NULL, type, load_value, NULL, 0)) { sge_strlcpy(sval, load_value, 100); /* -------------------------------- look for 'name' in our load_adjustments list */ if (job_load) { const char *s; double load_correction; s = lGetString(job_load, CE_stringval); if (!parse_ulong_val(&load_correction, NULL, type, s, err_str, 255)) { ERROR((SGE_EVENT, MSG_SCHEDD_LOADADJUSTMENTSVALUEXNOTNUMERIC_S , attrname)); } else if (lc_factor) { double old_dval; u_long32 relop; if (!strncmp(attrname, "np_", 3) && nproc != 1 ) { DPRINTF(("fillComplexFromHost: dividing lc_factor for \"%s\" with value %f by %d to %f\n", attrname, lc_factor, nproc, lc_factor / nproc)); lc_factor /= nproc; } load_correction *= lc_factor; /* it depends on relop in complex config whether load_correction is pos/neg */ if ( (relop = lGetUlong(cplx_el, CE_relop)) == CMPLXGE_OP || relop == CMPLXGT_OP){ old_dval = dval; dval += load_correction; } else{ old_dval = dval; dval -= load_correction; } sprintf(sval, "%8.3f", dval); DPRINTF(("%s: uc: %f c(%f): %f\n", attrname, old_dval, lc_factor, dval)); dom_type = DOMINANT_TYPE_CLOAD; } } /* we can have a user, who wants to override the incomming load value. This is no problem for consumables, but for fixed values. A custom fixed value is a per slot value (stored in CE_doubleval) and a load value is a per job value (stored in CE_pj_doubleval). This code changes a fixed custom value from a per slot to a per job value!! */ if ( !(lGetUlong(cplx_el, CE_dominant) == DOMINANT_TYPE_VALUE) && (lGetUlong(cplx_el, CE_pj_dominant) == DOMINANT_TYPE_VALUE)){ lSetDouble(cplx_el, CE_pj_doubleval, lGetDouble(cplx_el, CE_doubleval)); lSetString(cplx_el, CE_pj_stringval, lGetString(cplx_el, CE_stringval)); lSetUlong(cplx_el, CE_dominant, DOMINANT_TYPE_VALUE); lSetUlong(cplx_el, CE_pj_dominant, layer | DOMINANT_TYPE_FIXED); } if (!is_attr_prior2(cplx_el, dval, CE_pj_doubleval, CE_pj_dominant)){ lSetString(cplx_el, CE_pj_stringval, load_value); lSetUlong(cplx_el, CE_pj_dominant, layer | dom_type); lSetDouble(cplx_el, CE_pj_doubleval, dval ); } } /* end numerical load value */ lFreeList(&load_adjustments); }/* end block */ } } /* we are working on queue level, so we have to check for queue resource values */ if (queue){ bool created=false; if(!cplx_el){ cplx_el = lCopyElem(lGetElemStr(centry_list, CE_name, attrname)); if(!cplx_el){ /* error */ DRETURN(NULL); } lSetUlong(cplx_el, CE_dominant, DOMINANT_TYPE_VALUE); lSetUlong(cplx_el, CE_pj_dominant, DOMINANT_TYPE_VALUE); created = true; } if (!get_queue_resource(cplx_el, queue, attrname) && created) { lFreeElem(&cplx_el); } } DRETURN(cplx_el); }
/****** uti/spool/sge_get_management_entry() ************************************* * NAME * sge_get_management_entry() - Read management.properties file entries * * SYNOPSIS * int sge_get_management_entry(const char *fname, int n, * const char *name[], * char value[][1025], * dstring *error_dstring) * * FUNCTION * Reads in an array of configuration file entries * * RESULT * int - 0 on success * * BUGS * Function can not differ multiple similar named entries. * * NOTES * MT-NOTE: sge_get_management_entry() is MT safe ******************************************************************************/ int sge_get_management_entry(const char *fname, int n, int nmissing, bootstrap_entry_t name[], char value[][SGE_PATH_MAX], dstring *error_dstring) { FILE *fp; char buf[SGE_PATH_MAX], *cp; int i; bool *is_found = NULL; DENTER(TOP_LAYER, "sge_get_management_entry"); if (!(fp = fopen(fname, "r"))) { if (error_dstring == NULL){ CRITICAL((SGE_EVENT, MSG_FILE_FOPENFAILED_SS, fname, strerror(errno))); } else { sge_dstring_sprintf(error_dstring, MSG_FILE_FOPENFAILED_SS, fname, strerror(errno)); } DEXIT; return n; } is_found = malloc(sizeof(bool) * n); memset(is_found, false, n * sizeof(bool)); while (fgets(buf, sizeof(buf), fp)) { char *pos = NULL; /* set chrptr to the first non blank character * If line is empty continue with next line */ if(!(cp = strtok_r(buf, " \t\n", &pos))) { continue; } /* allow commentaries */ if (cp[0] == '#') { continue; } /* search for all requested configuration values */ for (i=0; i<n; i++) { char *nam = strtok_r(cp, "=", &pos); char *val = strtok_r(NULL, "\n", &pos); if (nam != NULL && strcasecmp(name[i].name, nam) == 0) { DPRINTF(("nam = %s\n", nam)); if (val != NULL) { DPRINTF(("val = %s\n", val)); sge_strlcpy(value[i], val, SGE_PATH_MAX); } else { sge_strlcpy(value[i], "", SGE_PATH_MAX); } is_found[i] = true; if (name[i].is_required) { --nmissing; } break; } } } if (nmissing != 0) { for (i=0; i<n; i++) { if (!is_found[i] && name[i].is_required) { if (error_dstring == NULL){ CRITICAL((SGE_EVENT, MSG_UTI_CANNOTLOCATEATTRIBUTEMAN_SS, name[i].name, fname)); } else { sge_dstring_sprintf(error_dstring, MSG_UTI_CANNOTLOCATEATTRIBUTEMAN_SS, name[i].name, fname); } break; } } } sge_free(&is_found); FCLOSE(fp); DEXIT; return nmissing; FCLOSE_ERROR: DEXIT; return 0; } /* sge_get_management_entry() */