/*___INFO__MARK_BEGIN__*/ /************************************************************************* * * The Contents of this file are made available subject to the terms of * the Sun Industry Standards Source License Version 1.2 * * Sun Microsystems Inc., March, 2001 * * * Sun Industry Standards Source License Version 1.2 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.2 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2001 by Sun Microsystems, Inc. * * All Rights Reserved. * ************************************************************************/ /*___INFO__MARK_END__*/ #include #include #include #include #include #include "sgermon.h" #include "sge_answer.h" #include "setup_path.h" #include "sge_unistd.h" #include "msg_common.h" #include "msg_clients_common.h" #include "sge_feature.h" #include "sge_uidgid.h" #include "sge_io.h" #include "sge_prog.h" #include "parse_job_cull.h" #include "parse_qsub.h" #include "read_defaults.h" #include "sgeobj/parse.h" #include "sge_options.h" #include "sgeobj/sge_job.h" static char *get_cwd_defaults_file_path (lList **answer_list); static void append_opts_from_default_files (u_long32 prog_number, lList **pcmdline, lList **answer_list, char **envp, char **def_files); /****** sge/opt/opt_list_append_opts_from_default_files() ********************* * NAME * opt_list_append_opts_from_default_files() -- parse default files * * SYNOPSIS * void opt_list_append_opts_from_default_files( * lList **pcmdline, * lList **answer_list * char **envp) * * FUNCTION * This function reads the 3 defaults 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 * * NOTES * MT-NOTE: opt_list_append_opts_from_default_files() is MT safe *******************************************************************************/ void opt_list_append_opts_from_default_files(u_long32 prog_number, const char* cell_root, const char* user, lList **pcmdline, lList **answer_list, char **envp) { dstring req_file = DSTRING_INIT; char *def_files[3 + 1]; DENTER(TOP_LAYER, "opt_list_append_opts_from_default_files"); lFreeList(answer_list); /* the sge root defaults file */ get_root_file_path(&req_file, cell_root, SGE_COMMON_DEF_REQ_FILE); def_files[0] = strdup(sge_dstring_get_string(&req_file)); /* * the defaults file in the user's home directory */ get_user_home_file_path(&req_file, SGE_HOME_DEF_REQ_FILE, user, answer_list); def_files[1] = strdup(sge_dstring_get_string(&req_file)); /* * the defaults file in the current working directory */ def_files[2] = get_cwd_defaults_file_path(answer_list); def_files[3] = NULL; /* * now read all the defaults files, unaware of where they came from */ append_opts_from_default_files(prog_number, pcmdline, answer_list, envp, def_files); /* MT-NOTE !!!! */ sge_dstring_free(&req_file); DRETURN_VOID; } /****** read_defaults/get_user_home_file_path() ***************************** * NAME * get_user_home_file_path() -- get absolut path name to file in user * home * * SYNOPSIS * char *get_user_home_file_path (lList **answer_list) * * FUNCTION * This function returns the path to the file in the user's home * directory * * INPUTS * dstring - computed absoult filename * const char *filename - file name * const char *user - user name * 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 * * RETURNS * bool - true or false * * MT-NOTE: get_user_home_file_path() is MT safe *******************************************************************************/ bool get_user_home_file_path(dstring *absolut_filename, const char *filename, const char *user, lList **answer_list) { bool ret = false; DENTER (TOP_LAYER, "get_user_home_file_path"); if (absolut_filename != NULL && filename != NULL) { sge_dstring_clear(absolut_filename); if (get_user_home(absolut_filename, user, answer_list)) { sge_dstring_append(absolut_filename, "/"); sge_dstring_append(absolut_filename, filename); ret = true; } } DRETURN(ret); } /****** sge/opt/get_cwd_defaults_file_path() *********************************** * NAME * get_cwd_defaults_file_path() -- find cwd default file path * * SYNOPSIS * char *get_cwd_defaults_file_path () * * FUNCTION * This function returns the path of the defaults file in the current working * directory * * INPUTS * 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 * - cwd defaults file name with absolute path * * MT-NOTE: get_cwd_defaults_file_path() is MT safe *******************************************************************************/ static char *get_cwd_defaults_file_path(lList **answer_list) { char cwd[SGE_PATH_MAX + 1]; char str[256 + 1]; char *file = NULL; DENTER (TOP_LAYER, "get_cwd_defaults_file_name"); if (!getcwd(cwd, sizeof(cwd))) { sprintf(str, MSG_FILE_CANTREADCURRENTWORKINGDIR); answer_list_add(answer_list, str, STATUS_EDISK, ANSWER_QUALITY_ERROR); } file = (char *)malloc(strlen(cwd) + strlen(SGE_HOME_DEF_REQ_FILE) + 2); strcpy(file, cwd); if (*file && (file[strlen(file) - 1] != '/')) { strcat(file, "/"); } strcat(file, SGE_HOME_DEF_REQ_FILE); DRETURN(file); } /****** 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; free(*pstr++)) { ; } DRETURN_VOID; } } for (pstr = def_files; *pstr; free(*pstr++)) { ; } DRETURN_VOID; } /****** sge/opt/opt_list_append_opts_from_qsub_cmdline() ********************** * NAME * opt_list_append_opts_from_qsub_cmdline() -- parse opts from cmd line * * SYNOPSIS * void opt_list_append_opts_from_qsub_cmdline(lList **opts_cmdline, * lList **answer_list, * char **argv, * char **envp) * * FUNCTION * Parse options from the qsub commandline given by "argv" and store * the parsed objects in "opts_cmdline". If an error occures store * the error/warning messages in the "answer_list". * "envp" is a pointer to the process environment. * * * INPUTS * lList **opts_cmdline - command line options * lList **answer_list - AN_Type list * char **argv - Argumente * char **envp - Environment * * RESULT * void - None *******************************************************************************/ void opt_list_append_opts_from_qsub_cmdline(u_long32 prog_number, lList **opts_cmdline, lList **answer_list, char **argv, char **envp) { lFreeList(answer_list); *answer_list = cull_parse_cmdline(prog_number, argv, envp, opts_cmdline, FLG_USE_PSEUDOS); } /****** sge/opt/opt_list_append_opts_from_qalter_cmdline() ******************** * NAME * opt_list_append_opts_from_qalter_cmdline() -- parse opts from cmd line * * SYNOPSIS * void opt_list_append_opts_from_qalter_cmdline(lList **opts_cmdline, * lList **answer_list, * char **argv, * char **envp) * * FUNCTION * Parse options from the qalter commandline given by "argv" and store * the parsed objects in "opts_cmdline". If an error occures store * the error/warning messages in the "answer_list". * "envp" is a pointer to the process environment. * * * INPUTS * lList **opts_cmdline - command line options * lList **answer_list - AN_Type list * char **argv - Argumente * char **envp - Environment * * RESULT * void - None *******************************************************************************/ void opt_list_append_opts_from_qalter_cmdline(u_long32 prog_number, lList **opts_cmdline, lList **answer_list, char **argv, char **envp) { lFreeList(answer_list); *answer_list = cull_parse_cmdline(prog_number, argv, envp, opts_cmdline, FLG_USE_PSEUDOS | FLG_QALTER); } /****** sge/opt/opt_list_append_opts_from_script() **************************** * NAME * opt_list_append_opts_from_script() -- parse opts from scriptfile * * SYNOPSIS * void opt_list_append_opts_from_script(lList **opts_scriptfile, * lList **answer_list, * const lList *opts_cmdline, * char **envp) * * FUNCTION * This function parses the commandline options which are embedded * in scriptfile (jobscript) and stores the parsed objects in * opts_scriptfile. The filename of the scriptfile has to be * contained in the list "opts_cmdline" which has been previously i * created with opt_list_append_opts_from_*_cmdline(). "answer_list" * will be used to store error/warning messages. * "envp" is a pointer to the process environment. * * INPUTS * lList **opts_scriptfile - embedded command line options * lList **answer_list - AN_Type list * const lList *opts_cmdline - Argumente * char **envp - Environment * * RESULT * void - None *******************************************************************************/ void opt_list_append_opts_from_script(u_long32 prog_number, lList **opts_scriptfile, lList **answer_list, const lList *opts_cmdline, char **envp) { lListElem *script_option = NULL; lListElem *c_option = NULL; const char *scriptfile = NULL; const char *prefix = NULL; script_option = lGetElemStr(opts_cmdline, SPA_switch, STR_PSEUDO_SCRIPT); if (script_option != NULL) { scriptfile = lGetString(script_option, SPA_argval_lStringT); } c_option = lGetElemStr(opts_cmdline, SPA_switch, "-C"); if (c_option != NULL) { prefix = lGetString(c_option, SPA_argval_lStringT); } else { prefix = default_prefix; } lFreeList(answer_list); *answer_list = parse_script_file(prog_number, scriptfile, prefix, opts_scriptfile, envp, FLG_DONT_ADD_SCRIPT); } /****** sge/opt/opt_list_append_opts_from_script_path() ************************ * NAME * opt_list_append_opts_from_script_path() -- parse opts from scriptfile * * SYNOPSIS * void opt_list_append_opts_from_script_path(lList **opts_scriptfile, * char *path, lList **answer_list, * const lList *opts_cmdline, * char **envp) * * FUNCTION * This function parses the commandline options which are embedded * in scriptfile (jobscript) and stores the parsed objects in * opts_scriptfile. The filename of the scriptfile has to be * contained in the list "opts_cmdline" which has been previously i * created with opt_list_append_opts_from_*_cmdline(). If the filename of * the scriptfile is not an absolute path, "path" will be prepended to it. * "answer_list" will be used to store error/warning messages. * "envp" is a pointer to the process environment. * * INPUTS * lList **opts_scriptfile - embedded command line options * const char *path - the root path for the script file * lList **answer_list - AN_Type list * const lList *opts_cmdline - Argumente * char **envp - Environment * * RESULT * void - None *******************************************************************************/ void opt_list_append_opts_from_script_path(u_long32 prog_number, lList **opts_scriptfile, const char *path, lList **answer_list, const lList *opts_cmdline, char **envp) { lListElem *script_option = NULL; lListElem *c_option = NULL; const char *scriptfile = NULL; char *scriptpath = NULL; const char *prefix = NULL; script_option = lGetElemStr(opts_cmdline, SPA_switch, STR_PSEUDO_SCRIPT); if (script_option != NULL) { scriptfile = lGetString(script_option, SPA_argval_lStringT); /* If the scriptfile path isn't absolute (which includes starting with $HOME), make it absolute relative to the given path. If the script or path is NULL, let parse_script_file() catch it. */ if ((scriptfile != NULL) && (path != NULL) && (scriptfile[0] != '/') && (strncmp (scriptfile, "$HOME/", 6) != 0) && (strcmp (scriptfile, "$HOME") != 0)) { /* Malloc space for the path, the filename, the \0, and perhaps a / */ scriptpath = (char *)malloc(sizeof(char) * (strlen(path) + strlen(scriptfile) + 2)); strcpy (scriptpath, path); /* If the last character is not a slash, add one. */ if (scriptpath[strlen (scriptpath) - 1] != '/') { strcat (scriptpath, "/"); } strcat (scriptpath, scriptfile); } else { scriptpath = strdup (scriptfile); } } c_option = lGetElemStr(opts_cmdline, SPA_switch, "-C"); if (c_option != NULL) { prefix = lGetString(c_option, SPA_argval_lStringT); } else { prefix = default_prefix; } lFreeList(answer_list); *answer_list = parse_script_file(prog_number, scriptpath, prefix, opts_scriptfile, envp, FLG_DONT_ADD_SCRIPT); FREE (scriptpath); } /****** sge/opt/opt_list_merge_command_lines() ******************************** * NAME * opt_list_merge_command_lines() -- merge commandlines together * * SYNOPSIS * void opt_list_merge_command_lines(lList **opts_all, * lList **opts_defaults, * lList **opts_scriptfile, * lList **opts_cmdline) * * FUNCTION * Merge "opts_defaults", "opts_scriptfile" and "opts_cmdline" into * "opts_all". * * Options to a sge submit can come from different sources: * - default settings (sge/sge_request) * - special comments in scriptfiles (override default settings) * - command line options (override default settings and special * comments) * * INPUTS * lList **opts_all - destination commandline * lList **opts_defaults - opts from default files * lList **opts_scriptfile - opts from the script * lList **opts_cmdline - commandline options * * RESULT * void - None *******************************************************************************/ void opt_list_merge_command_lines(lList **opts_all, lList **opts_defaults, lList **opts_scriptfile, lList **opts_cmdline) { /* * Order is very important here */ if (*opts_defaults != NULL) { if (*opts_all == NULL) { *opts_all = *opts_defaults; } else { lAddList(*opts_all, opts_defaults); } *opts_defaults = NULL; } if (*opts_scriptfile != NULL) { if (*opts_all == NULL) { *opts_all = *opts_scriptfile; } else { /* Override the queue (-q) values from defaults */ lOverrideStrList(*opts_all, *opts_scriptfile, SPA_switch, "-q"); } *opts_scriptfile = NULL; } if (*opts_cmdline != NULL) { if (*opts_all == NULL) { *opts_all = *opts_cmdline; } else { /* Override queue (-q) values from both defaults and scriptfile */ lOverrideStrList(*opts_all, *opts_cmdline, SPA_switch, "-q"); } *opts_cmdline = NULL; } /* If -ar was requested add -w if it was not explicit set */ if (lGetElemStr(*opts_all, SPA_switch, "-ar") != NULL) { if (lGetElemStr(*opts_all, SPA_switch, "-w") == NULL) { lListElem *ep_opt = sge_add_arg(opts_all, r_OPT, lIntT, "-w", "e"); lSetInt(ep_opt, SPA_argval_lIntT, ERROR_VERIFY); } } } /****** sge/opt/opt_list_has_X() ********************************************** * NAME * opt_list_has_X() -- is a certail option contained in list * * SYNOPSIS * bool opt_list_has_X(lList *opts, const char *option) * * FUNCTION * This function returns true (1) if the given 'option' * (e.g. "-help") is contained in the list 'opts'. * * INPUTS * lList *opts - SPA_Type list * const char *option - switch name * * RESULT * bool - found switch? * true - yes * false - no * * SEE ALSO * sge/opt/opt_list_is_X_true() *******************************************************************************/ bool opt_list_has_X(lList *opts, const char *option) { lListElem *opt; bool ret = false; opt = lGetElemStr(opts, SPA_switch, option); if (opt != NULL) { ret = true; } return ret; } /****** sge/opt/opt_list_is_X_true() ****************************************** * NAME * opt_list_is_X_true() -- check the state of a boolean switch * * SYNOPSIS * bool opt_list_is_X_true(lList *opts, const char *option) * * FUNCTION * This function returns true (1) if the given 'option' * (e.g. "-b") is contained in the list 'opts' and if * it was set to 'true'. If the value of the boolean switch * is false than the function will also return false (0). * * INPUTS * lList *opts - SPA_Type list * const char *option - switch name * * RESULT * bool - found switch with value 'true' * true - yes * false - no * * SEE ALSO * sge/opt/opt_list_has_X() ******************************************************************************/ bool opt_list_is_X_true(lList *opts, const char *option) { lListElem *opt; bool ret = false; opt = lGetElemStr(opts, SPA_switch, option); if (opt != NULL) { ret = (lGetInt(opt, SPA_argval_lIntT) == 1) ? true : false; } return ret; } /****** read_defaults/get_root_file_path() ************************************* * NAME * get_root_file_path() -- creates absolute filename for file in SGE_ROOT * * SYNOPSIS * const char* get_root_file_path(dstring *absolut_filename, const char * *cell_root, const char *filename) * * FUNCTION * Sets the absolut filename of a file in SGE_ROOT in the given dstring * * INPUTS * dstring *absolut_filename - created absolut filename * const char *cell_root - sge root patch * const char *filename - file name * * RESULT * const char* - pointer to filename in absolut_filename * * NOTES * MT-NOTE: get_root_file_path() is MT safe * *******************************************************************************/ const char *get_root_file_path(dstring *absolut_filename, const char *cell_root, const char *filename) { DENTER (TOP_LAYER, "get_root_file_path"); sge_dstring_sprintf(absolut_filename, "%s/%s", cell_root, filename); DRETURN(sge_dstring_get_string(absolut_filename)); } /****** read_defaults/get_user_home() ****************************************** * NAME * get_user_home() -- get absoult filename in users home dir * * SYNOPSIS * bool get_user_home(dstring *home_dir, const char *user, lList * **answer_list) * * FUNCTION * Sets the absolut filename of a file in the users home directory * * INPUTS * dstring *home_dir - created absolut filename * const char *user - user * lList **answer_list - answer list * * RESULT * bool - true on success * false on error * * NOTES * MT-NOTE: get_user_home() is MT safe * *******************************************************************************/ bool get_user_home(dstring *home_dir, const char *user, lList **answer_list) { bool ret = true; DENTER(TOP_LAYER, "get_user_home"); if (home_dir != NULL) { struct passwd *pwd; struct passwd pw_struct; char *buffer; int size; size = get_pw_buffer_size(); buffer = sge_malloc(size); pwd = sge_getpwnam_r(user, &pw_struct, buffer, size); if (!pwd) { answer_list_add_sprintf(answer_list, STATUS_ENOSUCHUSER, ANSWER_QUALITY_ERROR, MSG_USER_INVALIDNAMEX_S, user); ret = false; } if (ret && !pwd->pw_dir) { answer_list_add_sprintf(answer_list, STATUS_EDISK, ANSWER_QUALITY_ERROR, MSG_USER_NOHOMEDIRFORUSERX_S, user); ret = false; } if (ret) { sge_dstring_copy_string(home_dir, pwd->pw_dir); } FREE(buffer); } else { /* should never happen */ ret = false; } DRETURN(ret); }