/****** uti/io/sge_filecmp() ************************************************** * NAME * sge_filecmp() -- Compare two files * * SYNOPSIS * int sge_filecmp(const char *name0, const char *name1) * * FUNCTION * Compare two files. They are equal if: * - both of them have the same name * - if a stat() succeeds for both files and * i-node/device-id are equal * * we are not sure * - if stat() failes for at least one of the files * (It could be that both pathes direct to the same * file not existing) * * INPUTS * const char *name0 - 1st filename * const char *name1 - 2nd filename * * RESULT * int - Identical? * 0 - Yes. * 1 - No they are not equivalent. * * NOTES * MT-NOTE: sge_filecmp() is MT safe ******************************************************************************/ int sge_filecmp(const char *name0, const char *name1) { SGE_STRUCT_STAT buf0, buf1; DENTER(TOP_LAYER, "filecmp"); if (!strcmp(name0, name1)) { DEXIT; return 0; } if (SGE_STAT(name0, &buf0)<0) { DEXIT; return 1; } if (SGE_STAT(name1, &buf1)<0) { DEXIT; return 1; } if (buf0.st_ino == buf1.st_ino && buf0.st_dev == buf1.st_dev) { DEXIT; return 0; } else { DEXIT; return 1; } }
/****** 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; }
/****** count_exit_status ***************************************************** * NAME * count_exit_status() -- Return the number of lines in the exit status file * * SYNOPSIS * int count_exit_status(void) * * FUNCTION * Returns the number of lines in the exit_status file. * Each pe_start, prolog, job, epilog and pe_stop write a line to the * exit_status file. * This function is used to detect where the shepherd fails. * * INPUTS * void - none * * RESULT * int - Number of lines in the exit_status file. *******************************************************************************/ int count_exit_status(void) { int n = 0; SGE_STRUCT_STAT sbuf; if (!SGE_STAT("exit_status", &sbuf) && sbuf.st_size) { FILE *fp; if ((fp = fopen("exit_status", "r"))) { char buf[1024]; while (fgets(buf, sizeof(buf), fp)) { int dummy; if (sscanf(buf, "%d\n", &dummy) == 1) { n++; } } FCLOSE(fp); } } FCLOSE_ERROR: return n; }
/****** uti/prog/sge_get_alias_path() ***************************************** * NAME * sge_get_alias_path() -- Return the path of the 'alias_file' * * SYNOPSIS * const char* sge_get_alias_path(void) * * FUNCTION * Return the path of the 'alias_file' * * NOTES * MT-NOTE: sge_get_alias_path() is MT safe * ******************************************************************************/ const char *sge_get_alias_path(void) { const char *sge_root, *sge_cell; char *cp; int len; SGE_STRUCT_STAT sbuf; DENTER_(TOP_LAYER, "sge_get_alias_path"); sge_root = sge_get_root_dir(1, NULL, 0, 1); sge_cell = sge_get_default_cell(); if (SGE_STAT(sge_root, &sbuf)) { CRITICAL((SGE_EVENT, MSG_SGETEXT_SGEROOTNOTFOUND_S , sge_root)); SGE_EXIT(NULL, 1); } len = strlen(sge_root) + strlen(sge_cell) + strlen(COMMON_DIR) + strlen(ALIAS_FILE) + 5; if (!(cp = malloc(len))) { CRITICAL((SGE_EVENT, MSG_MEMORY_MALLOCFAILEDFORPATHTOHOSTALIASFILE )); SGE_EXIT(NULL, 1); } sprintf(cp, "%s/%s/%s/%s", sge_root, sge_cell, COMMON_DIR, ALIAS_FILE); DRETURN_(cp); }
char *qmonReadText(const char *filename, lList **alpp) { char *text = NULL; SGE_STRUCT_STAT statb; FILE *fp = NULL; DENTER(GUI_LAYER, "qmonReadText"); if (filename == NULL) { answer_list_add_sprintf(alpp, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR, "No filename specified"); DRETURN(NULL); } /* ** make sure the file is a regular text file and open it */ if (SGE_STAT(filename, &statb) == -1 || (statb.st_mode & S_IFMT) != S_IFREG || !(fp = fopen(filename, "r"))) { answer_list_add_sprintf(alpp, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR, MSG_FILE_OPENFAILED_S, filename); DRETURN(NULL); } /* ** put the contents of the file in the Text widget by allocating ** enough space for the entire file, reading the file into the ** allocated space, and using XmTextFieldSetString() to show the file. */ if ((text = XtMalloc((unsigned)(statb.st_size + 1))) == NULL) { answer_list_add_sprintf(alpp, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR, "%s", MSG_MEMORY_MALLOCFAILED); FCLOSE(fp); DRETURN(NULL); } if (!fread(text, sizeof (char), statb.st_size + 1, fp)) { answer_list_add_sprintf(alpp, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR, MSG_FILE_FREADFAILED_SS, filename, strerror(errno)); } text[statb.st_size] = 0; /* be sure to NULL-terminate */ FCLOSE(fp); DRETURN(text); FCLOSE_ERROR: XtFree(text); answer_list_add_sprintf(alpp, STATUS_ESYNTAX, ANSWER_QUALITY_ERROR, MSG_FILE_NOCLOSE_SS, filename, strerror(errno)); DRETURN(NULL); }
/******* execd/loadsensor/sge_ls_create_ls() ********************************** * NAME * sge_ls_create_ls -- creates a new CULL loadsensor element * * SYNOPSIS * static lListElem* sge_ls_create_ls(const char *qualified_hostname, * char *name, const char *scriptfile) * * FUNCTION * The function creates a new CULL element of type LS_Type and * returns a pointer to this object. The loadsensor will be * started immediately. * If it cannot be started then, LS_has_to_restart is set to * true so that it will be attempted to be restarted in the next load interval * * INPUTS * qualified_hostname - qualified host name * name - pseudo name of the ls * "extern" for user defined loadsensors * "intern" for qidle and qloadsensor * scriptfile - absolute path to the ls scriptfile * * RESULT * new CULL element of type LS_Type will be returned * and a new loadsensor process will be created by this function ******************************************************************************/ static lListElem *sge_ls_create_ls(const char *qualified_hostname, char *name, const char *scriptfile) { lListElem *new_ls = NULL; /* LS_Type */ SGE_STRUCT_STAT st; DENTER(TOP_LAYER, "sge_ls_create_ls"); if (scriptfile != NULL) { if (SGE_STAT(scriptfile, &st) != 0) { if (strcmp(name, "extern") == 0) { WARNING((SGE_EVENT, MSG_LS_NOMODTIME_SS, scriptfile, strerror(errno))); } DRETURN(NULL); } new_ls = lCreateElem(LS_Type); if (new_ls) { /* initialize all attributes */ lSetString(new_ls, LS_name, name); lSetString(new_ls, LS_command, scriptfile); sge_ls_set_pid(new_ls, -1); lSetRef(new_ls, LS_in, NULL); lSetRef(new_ls, LS_out, NULL); lSetRef(new_ls, LS_err, NULL); lSetBool(new_ls, LS_has_to_restart, false); lSetUlong(new_ls, LS_tag, 0); lSetList(new_ls, LS_incomplete, lCreateList("", LR_Type)); lSetList(new_ls, LS_complete, lCreateList("", LR_Type)); lSetUlong(new_ls, LS_last_mod, st.st_mtime); /* start loadsensor, if couldn't set the restart flag so that we * restart it in the next load interval */ if (sge_ls_start_ls(qualified_hostname, new_ls) != LS_OK) { lSetBool(new_ls, LS_has_to_restart, true); } } } DRETURN(new_ls); }
/****** uti/afsutil/sge_read_token() ****************************************** * NAME * sge_read_token() -- read token from file * * SYNOPSIS * char* sge_read_token(const char *file) * * FUNCTION * Read token from file, malloc buffer, add '\0' byte and * return pointer to buffer. * * INPUTS * const char *file - filename * * NOTES * MT-NOTE: sge_read_token() is MT safe * * RESULT * char* - pointer to a malloced buffer or * NULL if error occured ******************************************************************************/ char *sge_read_token(const char *file) { SGE_STRUCT_STAT sb; int fd; char *tokenbuf; size_t size; DENTER(TOP_LAYER, "sge_read_token"); if (SGE_STAT(file, &sb)) { DTRACE; return NULL; } size = sb.st_size + 1; if (((SGE_OFF_T)size != sb.st_size + 1) || (tokenbuf = (char *) malloc(size)) == NULL) { DTRACE; return NULL; } if ((fd = SGE_OPEN2(file, O_RDONLY)) == -1) { DTRACE; return NULL; } if (read(fd, tokenbuf, sb.st_size) != sb.st_size) { DTRACE; close(fd); return NULL; } tokenbuf[sb.st_size] = '\0'; close(fd); DEXIT; return tokenbuf; }
int pt_dispatch_proc_to_job( lnk_link_t *job_list, int time_stamp, time_t last_time ) { char procnam[128]; int fd = -1; #if defined(LINUX) char buffer[BIGLINE]; lListElem *pr = NULL; SGE_STRUCT_STAT fst; unsigned long utime, stime, vsize, pid; int pos_pid = lGetPosInDescr(PRO_Type, PRO_pid); int pos_utime = lGetPosInDescr(PRO_Type, PRO_utime); int pos_stime = lGetPosInDescr(PRO_Type, PRO_stime); int pos_vsize = lGetPosInDescr(PRO_Type, PRO_vsize); int pos_groups = lGetPosInDescr(PRO_Type, PRO_groups); int pos_rel = lGetPosInDescr(PRO_Type, PRO_rel); int pos_run = lGetPosInDescr(PRO_Type, PRO_run); int pos_io = lGetPosInDescr(PRO_Type, PRO_io); int pos_group = lGetPosInDescr(GR_Type, GR_group); #else prstatus_t pr; prpsinfo_t pri; #endif #if defined(SOLARIS) || defined(ALPHA) prcred_t proc_cred; #endif int ret; u_long32 max_groups; gid_t *list; int groups=0; int pid_tmp; proc_elem_t *proc_elem = NULL; job_elem_t *job_elem = NULL; lnk_link_t *curr; double old_time = 0; uint64 old_vmem = 0; DENTER(TOP_LAYER, "pt_dispatch_proc_to_job"); max_groups = sge_sysconf(SGE_SYSCONF_NGROUPS_MAX); if (max_groups <= 0) { ERROR((SGE_EVENT, SFNMAX, MSG_SGE_NGROUPS_MAXOSRECONFIGURATIONNECESSARY)); DEXIT; return 1; } list = (gid_t*) malloc(max_groups*sizeof(gid_t)); if (list == NULL) { ERROR((SGE_EVENT, SFNMAX, MSG_SGE_PTDISPATCHPROCTOJOBMALLOCFAILED)); DEXIT; return 1; } /* find next valid entry in procfs */ while ((dent = readdir(cwd))) { char *pidname; if (!dent->d_name) continue; if (!dent->d_name[0]) continue; if (!strcmp(dent->d_name, "..") || !strcmp(dent->d_name, ".")) continue; if (dent->d_name[0] == '.') pidname = &dent->d_name[1]; else pidname = dent->d_name; if (atoi(pidname) == 0) continue; #if defined(LINUX) /* check only processes which belongs to a GE job */ if ((pr = get_pr(atoi(pidname))) != NULL) { /* set process as still running */ lSetPosBool(pr, pos_run, true); if (lGetPosBool(pr, pos_rel) != true) { continue; } } sprintf(procnam, PROC_DIR "/%s/stat", dent->d_name); if (SGE_STAT(procnam, &fst)) { if (errno != ENOENT) { #ifdef MONITOR_PDC INFO((SGE_EVENT, "could not stat %s: %s\n", procnam, strerror(errno))); #endif touch_time_stamp(dent->d_name, time_stamp, job_list); } continue; } /* TODO (SH): This does not work with Linux 2.6. I'm looking for a workaround. * If the stat file was not changed since our last parsing there is no need to do it again */ /*if (pr == NULL || fst.st_mtime > last_time) {*/ { #else sprintf(procnam, "%s/%s", PROC_DIR, dent->d_name); #endif if ((fd = open(procnam, O_RDONLY, 0)) == -1) { if (errno != ENOENT) { #ifdef MONITOR_PDC if (errno == EACCES) INFO((SGE_EVENT, "(uid:"gid_t_fmt" euid:"gid_t_fmt") could not open %s: %s\n", getuid(), geteuid(), procnam, strerror(errno))); else INFO((SGE_EVENT, "could not open %s: %s\n", procnam, strerror(errno))); #endif touch_time_stamp(dent->d_name, time_stamp, job_list); } continue; } /** ** get a list of supplementary group ids to decide ** whether this process will be needed; ** read also prstatus **/ # if defined(LINUX) /* * Read the line and append a 0-Byte */ if ((ret = read(fd, buffer, BIGLINE-1))<=0) { close(fd); if (ret == -1 && errno != ENOENT) { #ifdef MONITOR_PDC INFO((SGE_EVENT, "could not read %s: %s\n", procnam, strerror(errno))); #endif touch_time_stamp(dent->d_name, time_stamp, job_list); } continue; } buffer[BIGLINE-1] = '\0'; /* * get prstatus */ ret = sscanf(buffer, "%lu %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %*d %*d %*d %*d %*d %*d %*u %lu", &pid, &utime, &stime, &vsize); if (ret != 4) { close(fd); continue; } if (pr == NULL) { pr = lCreateElem(PRO_Type); lSetPosUlong(pr, pos_pid, pid); lSetPosBool(pr, pos_rel, false); append_pr(pr); } lSetPosUlong(pr, pos_utime, utime); lSetPosUlong(pr, pos_stime, stime); lSetPosUlong(pr, pos_vsize, vsize); close(fd); } /* mark this proc as running */ lSetPosBool(pr, pos_run, true); /* * get number of groups; * get list of supplementary groups */ { char procnam[256]; lList *groupTable = lGetPosList(pr, pos_groups); sprintf(procnam, PROC_DIR "/%s/status", dent->d_name); if (SGE_STAT(procnam, &fst) != 0) { if (errno != ENOENT) { #ifdef MONITOR_PDC INFO((SGE_EVENT, "could not stat %s: %s\n", procnam, strerror(errno))); #endif touch_time_stamp(dent->d_name, time_stamp, job_list); } continue; } groups = 0; if (fst.st_mtime < last_time && groupTable != NULL) { lListElem *group; for_each(group, groupTable) { list[groups] = lGetPosUlong(group, pos_group); groups++; } } else {
/****** sge/opt/append_opts_from_default_files() ******************************* * NAME * append_opts_from_default_files() -- parse default files * * SYNOPSIS * void append_opts_from_default_files(lList **pcmdline, * lList **answer_list * char **envp, * char *def_files) * * FUNCTION * This function reads the defaults files pointed to by def_files[] if they * exist and parses them into an options list. * * INPUTS * lList **pcmdline - pointer to SPA_Type list, if list is NULL, it is * created if the files contain any options * lList* - answer list, AN_Type or NULL if everything ok * possible errors: * STATUS_ENOSUCHUSER - could not retrieve passwd info on me.user_name * STATUS_EDISK - home directory for user is missing or cwd * cannot be read or file could not be opened * (is just a warning) * STATUS_EEXIST - (parse_script_file), (is just a warning) * STATUS_EUNKNOWN - (parse_script_file), error opening or * reading from existing file, (is just a warning) * plus all other error stati returned by * parse_script_file, see there * char **envp - environment pointer * char **def_files - paths to default files * *******************************************************************************/ static void append_opts_from_default_files(u_long32 prog_number, lList **pcmdline, lList **answer_list, char **envp, char **def_files) { lList *alp; lListElem *aep; char **pstr; char **ppstr; SGE_STRUCT_STAT buf; int do_exit = 0; DENTER(TOP_LAYER, "append_opts_from_default_files"); for (pstr = def_files; *pstr; pstr++) { int already_read; if (SGE_STAT(*pstr, &buf)<0) { DPRINTF(("-- defaults file %s does not exist\n", *pstr)); continue; } already_read = 0; for (ppstr = def_files; *ppstr != *pstr; ppstr++) { if (!sge_filecmp(*ppstr, *pstr)) { DPRINTF(("-- skipping %s as defaults file - already read as %s\n", *pstr, *ppstr)); already_read = 1; break; } } if (already_read) { continue; } DPRINTF(("-- defaults file: %s\n", *pstr)); alp = parse_script_file(prog_number, *pstr, "", pcmdline, envp, FLG_HIGHER_PRIOR | FLG_USE_NO_PSEUDOS); for_each(aep, alp) { u_long32 status; answer_quality_t quality; status = lGetUlong(aep, AN_status); quality = (answer_quality_t)lGetUlong(aep, AN_quality); if (quality == ANSWER_QUALITY_ERROR) { DPRINTF(("%s", lGetString(aep, AN_text))); if (status == STATUS_EDISK) { /* ** we turn this error into a warning here */ quality = ANSWER_QUALITY_WARNING; } else { do_exit = 1; } } else { DPRINTF(("Warning: Error: %s\n", lGetString(aep, AN_text))); } answer_list_add(answer_list, lGetString(aep, AN_text), status, quality); } lFreeList(&alp); if (do_exit) { for (pstr = def_files; *pstr; pstr++) { sge_free(pstr); } DRETURN_VOID; } }
int checkpointed_file_exists(void) { SGE_STRUCT_STAT buf; return !SGE_STAT("checkpointed", &buf); }
/****** uti/io/sge_file2string() ********************************************** * NAME * sge_file2string() -- Load file into string * * SYNOPSIS * char* sge_file2string(const char *fname, int *len) * * FUNCTION * Load file into string. Returns a pointer to a string buffer containing * the file contents and the size of the buffer (= number of bytes read) * in the variable len. * If the file cannot be read (doesn't exist, permissions etc.), NULL is * returned as buffer and len is set to 0. * * INPUTS * const char *fname - filename * int *len - number of bytes read * * RESULT * char* - malloced string buffer * * SEE ALSO * uti/io/sge_string2file() * uti/io/sge_stream2string() * * NOTES * MT-NOTE: sge_file2string() is MT safe ******************************************************************************/ char *sge_file2string(const char *fname, int *len) { FILE *fp; SGE_STRUCT_STAT statbuf; int size, i; char *str; DENTER(CULL_LAYER, "sge_file2string"); /* initialize len - in case of errors we want to return 0 * JG: TODO: it would be better to return -1. Check if calling * functions would handle this situation. */ if (len != NULL) { *len = 0; } /* try file access, read file info */ if (SGE_STAT(fname, &statbuf)) { DEXIT; return NULL; } size = statbuf.st_size; if ((fp = fopen(fname, "r")) == NULL) { ERROR((SGE_EVENT, MSG_FILE_FOPENFAILED_SS, fname, strerror(errno))); DEXIT; return NULL; } if ((str = malloc(size+1)) == NULL) { FCLOSE(fp); DEXIT; return NULL; } str[0] = '\0'; /* ** With fread(..., size, 1, ...), ** Windows cannot read <size> bytes here, because in ** text mode the trailing ^Z is ignored. ** CRLF -> LF conversion reduces size even further. ** Therefore, the file has less than size-1 bytes if read ** in text (ascii) mode. ** Correctly, fread returns 0, because 0 elements of ** size <size> were read. */ if (size > 0) { #ifdef WIN32 /* fread call and evaluation of return value is different */ i = fread(str, 1, size, fp); if (i == 0) { sge_free(&str); FCLOSE(fp); DEXIT; return NULL; } str[i] = '\0'; /* delimit this string */ if (len != NULL) { *len = i; } #else i = fread(str, size, 1, fp); if (i != 1) { ERROR((SGE_EVENT, MSG_FILE_FREADFAILED_SS, fname, strerror(errno))); sge_free(&str); FCLOSE(fp); DEXIT; return NULL; } str[size] = '\0'; /* delimit this string */ if (len != NULL) { *len = size; } #endif } FCLOSE(fp); DEXIT; return str; FCLOSE_ERROR: sge_free(&str); DEXIT; return NULL; }
/****** 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; }
/****** Interactive/qrsh/setEnvironment() *************************************** * * NAME * setEnvironment() -- set environment from file * * SYNOPSIS * static char *setEnvironment(const char *jobdir, char **wrapper); * * FUNCTION * Reads environment variables and their values from file <envFileName> * and sets them in the actual process environment. * The file format conforms to the sge environment file format: * Each line contains a tuple: * <name>=<value> * Special handling for variable PWD: tries to change to named * directory. * Special handling for variable QRSH_COMMAND: is the command to be executed * by qrsh_starter. The value of this variable will be returned as command, * or NULL, if an error occurs. * Special handling for variable QRSH_WRAPPER: this is a wrapper to be called * instead of a shell to execute the command. * If this variable is contained in the environment, it will be returned in * the parameter wrapper. Memory will be allocated to hold the variable, it * is in the responsibility of the caller to free this memory. * Special handling for variable DISPLAY: if it is already set, do not * overwrite it. Usually it is not set, but if ssh is used as transport * mechanism for qrsh, the ssh -X option can be used to enable * X11 forwarding. * * INPUTS * jobdir - the jobs spool directory * wrapper - buffer to take the path and name of a wrapper script * * RESULT * command, if all actions could be performed * NULL, if an error occured; possible errors are: * - the environment file cannot be opened * - a PWD entry is found, but changing to the named directory fails * - necessary memory cannot be allocated * - the variable QRSH_COMMAND is not found * **************************************************************************** */ static char *setEnvironment(const char *jobdir, char **wrapper) { char envFileName[SGE_PATH_MAX]; FILE *envFile = NULL; char *line = NULL; char *command = NULL; SGE_STRUCT_STAT statbuf; int size; bool set_display = true; *wrapper = NULL; /* don't set DISPLAY, if it is already set (e.g. by ssh) */ if (getenv("DISPLAY") != NULL) { set_display = false; } snprintf(envFileName, SGE_PATH_MAX, "%s/environment", jobdir); /* check if environment file exists and * retrieve file size. We will take file size as maximum possible line length */ if (SGE_STAT(envFileName, &statbuf) != 0) { qrsh_error(MSG_QRSH_STARTER_CANNOTOPENFILE_SS, envFileName, strerror(errno)); return NULL; } size = statbuf.st_size; line = (char *)malloc(size + 1); if (line == NULL) { qrsh_error(MSG_QRSH_STARTER_MALLOCFAILED_S, strerror(errno)); return NULL; } /* open sge environment file */ if ((envFile = fopen(envFileName, "r")) == NULL) { qrsh_error(MSG_QRSH_STARTER_CANNOTOPENFILE_SS, envFileName, strerror(errno)); sge_free(&line); return NULL; } /* set all environment variables, change to directory named by PWD */ while (fgets(line, size, envFile) != NULL) { /* clean trailing garbage (\n, \r, EOF ...) */ char *c = &line[strlen(line)]; while (iscntrl(*(--c))) { *c = 0; } /* skip setting of display variable */ if (strncmp(line, "DISPLAY=", 8) == 0 && !set_display) { continue; } if (strncmp(line, "QRSH_COMMAND=", 13) == 0) { if ((command = (char *)malloc(strlen(line) - 13 + 1)) == NULL) { qrsh_error(MSG_QRSH_STARTER_MALLOCFAILED_S, strerror(errno)); sge_free(&line); FCLOSE(envFile); return NULL; } strcpy(command, line + 13); } else if (strncmp(line, "QRSH_WRAPPER=", 13) == 0) { if (*(line + 13) == 0) { fprintf(stderr, "%s\n", MSG_QRSH_STARTER_EMPTY_WRAPPER); } else { if ((*wrapper = (char *)malloc(strlen(line) - 13 + 1)) == NULL) { qrsh_error(MSG_QRSH_STARTER_MALLOCFAILED_S, strerror(errno)); sge_free(&line); FCLOSE(envFile); return NULL; } strcpy(*wrapper, line + 13); } } else { const char *new_line = sge_replace_substring(line, "\\n", "\n"); int put_ret; /* set variable */ if (new_line != NULL) { put_ret = sge_putenv(new_line); sge_free(&new_line); } else { put_ret = sge_putenv(line); } if (put_ret == 0) { sge_free(&line); FCLOSE(envFile); return NULL; } } } sge_free(&line); FCLOSE(envFile); /* * Use starter_method if it is supplied * and not overridden by QRSH_WRAPPER */ if (*wrapper == NULL) { char *starter_method = get_conf_val("starter_method"); if (starter_method != NULL && strcasecmp(starter_method, "none") != 0) { char buffer[128]; *wrapper = starter_method; snprintf(buffer, 128, "%s=%s", "SGE_STARTER_SHELL_PATH", ""); sge_putenv(buffer); snprintf(buffer, 128, "%s=%s", "SGE_STARTER_SHELL_START_MODE", "unix_behavior"); sge_putenv(buffer); snprintf(buffer, 128, "%s=%s", "SGE_STARTER_USE_LOGIN_SHELL", "false"); sge_putenv(buffer); } } return command; FCLOSE_ERROR: qrsh_error(MSG_FILE_ERRORCLOSEINGXY_SS, envFileName, strerror(errno)); return NULL; }