/****** execd/loadsensor/sge_ls_start_ls() ************************************ * NAME * sge_ls_start_ls -- starts a loadsensor * * SYNOPSIS * static void sge_ls_start_ls(const char *qualified_hostname, lListElem *this_ls) * * FUNCTION * An additional loadsensor process will be started. The name * of the script has to be stored in the LS_command entry of * 'this_ls' before this function will be called. * * The process environment of the loadsensor will contain * the HOST variable. This variable contains the hostname * of the execution daemon which calls this function. * * If 'this_ls' correlates to the 'qidle'-loadsensor then * also the XAUTHORITY environment variable will be set. * * INPUTS * qualified_hostname - qualified host name * this_ls - pointer to a CULL element of type LS_Type * * RESULT * An additional loadsensor process will be started. * [this_ls] - the CULL element will be modified * LS_pid contains the pid of the ls process * LS_in, LS_out, LS_err are the FILE-streams for the * communication with the ls-process * returns LS_OK * If sge_peopen fails, returns LS_CANT_PEOPEN ******************************************************************************/ static int sge_ls_start_ls(const char *qualified_hostname, lListElem *this_ls) { pid_t pid = -1; FILE *fp_in = NULL; FILE *fp_out = NULL; FILE *fp_err = NULL; char buffer[1024]; char **envp = NULL; DENTER(TOP_LAYER, "sge_ls_start_ls"); snprintf(buffer, sizeof(buffer), "%s=%s", "HOST", qualified_hostname); if (has_to_use_qidle && !strcmp(lGetString(this_ls, LS_name), IDLE_LOADSENSOR_NAME)) { envp = sge_malloc(sizeof(char *) * 3); envp[0] = buffer; envp[1] = "XAUTHORITY=/tmp/.xauthority"; envp[2] = NULL; } else { envp = sge_malloc(sizeof(char *) * 2); envp[0] = buffer; envp[1] = NULL; } /* we need fds for select() .. */ pid = sge_peopen("/bin/sh", 0, lGetString(this_ls, LS_command), NULL, envp, &fp_in, &fp_out, &fp_err, true); if (envp) { sge_free(&envp); } if (pid == -1) { return LS_CANT_PEOPEN; } /* we need load reports non blocking */ fcntl(fileno(fp_out), F_SETFL, O_NONBLOCK); sge_ls_set_pid(this_ls, pid); lSetRef(this_ls, LS_in, fp_in); lSetRef(this_ls, LS_out, fp_out); lSetRef(this_ls, LS_err, fp_err); DPRINTF(("%s: successfully started load sensor \"%s\"\n", SGE_FUNC, lGetString(this_ls, LS_command))); /* request first load report after starting */ ls_send_command(this_ls, "\n"); return LS_OK; }
/****** binding_support/get_processor_ids() ****************************** * NAME * get_processor_ids() -- Get internal processor ids for a specific core. * * SYNOPSIS * bool get_processor_ids(int socket_number, int core_number, int** * proc_ids, int* amount) * * FUNCTION * Get the internal processor ids for a given core (specified by a socket, * core pair). * * INPUTS * int socket_number - Logical socket number (starting at 0 without holes) * int core_number - Logical core number on the socket (starting at 0 without holes) * * OUTPUTS * int** proc_ids - Array of internal processor ids. * int* amount - Size of the proc_ids array. * * RESULT * bool - Returns true when processor ids where found otherwise false. * * NOTES * MT-NOTE: get_processor_ids() is MT safe * *******************************************************************************/ bool get_processor_ids(int socket_number, int core_number, int** proc_ids, int* amount) { #if HAVE_HWLOC int i, count; hwloc_obj_t pu, parent; struct hwloc_obj **children; hwloc_obj_t core = hwloc_get_obj_below_by_type(sge_hwloc_topology, HWLOC_OBJ_SOCKET, socket_number, HWLOC_OBJ_CORE, core_number); if (core) pu = hwloc_get_obj_below_by_type(sge_hwloc_topology, HWLOC_OBJ_CORE, core->logical_index, HWLOC_OBJ_PU, 0); else return false; parent = pu->parent; count = parent->arity; if (count <= 0) return false; children = parent->children; (*amount) = count; (*proc_ids) = (int *) sge_malloc(count * sizeof(int)); for (i = 0; i < count; i++) (*proc_ids)[i] = children[i]->os_index; return true; #else return false; #endif }
sge_bootstrap_state_class_t *sge_bootstrap_state_class_create(sge_path_state_class_t *sge_paths, sge_error_class_t *eh) { sge_bootstrap_state_class_t *ret = (sge_bootstrap_state_class_t *)sge_malloc(sizeof(sge_bootstrap_state_class_t)); DENTER(TOP_LAYER, "sge_bootstrap_state_class_create"); if (!ret) { if (eh != NULL) { eh->error(eh, STATUS_EMALLOC, ANSWER_QUALITY_ERROR, "%s", MSG_MEMORY_MALLOCFAILED); } DEXIT; return NULL; } if( !sge_bootstrap_state_class_init(ret, eh) ) { sge_bootstrap_state_class_destroy(&ret); DEXIT; return NULL; } /* TODO move the following block into sge_bootstrap_state_class_init and delete bootstrap_setup */ if (!sge_bootstrap_state_setup(ret, sge_paths, eh)) { sge_bootstrap_state_class_destroy(&ret); DEXIT; return NULL; } DEXIT; return ret; }
int ptys_open(int fdm, char *pts_name) { struct group gr_struct; struct group *grptr; int gid, fds; char *gr_buffer; size_t gr_buffer_size; gr_buffer_size = get_group_buffer_size(); gr_buffer = sge_malloc(gr_buffer_size); if (getgrnam_r("tty", &gr_struct, gr_buffer, gr_buffer_size, &grptr) == 0) { gid = grptr->gr_gid; } else { gid = -1; /* group tty is not in the group file */ } sge_free(&gr_buffer); /* following two functions don't work unless we're root */ chown(pts_name, getuid(), gid); chmod(pts_name, S_IRUSR | S_IWUSR | S_IWGRP); if ((fds = open(pts_name, O_RDWR)) < 0) { close(fdm); return -1; } return fds; }
static void sge_error_verror(sge_error_class_t* thiz, int error_type, int error_quality, const char*format, va_list ap) { sge_error_message_t *error = NULL; sge_error_t *et = (sge_error_t*)thiz->sge_error_handle; dstring ds = DSTRING_INIT; DENTER(TOP_LAYER, "sge_error_verror"); error = (sge_error_message_t*)sge_malloc(sizeof(sge_error_message_t)); error->error_quality = error_quality; error->error_type = error_type; sge_dstring_vsprintf(&ds, format, ap); error->message = strdup(sge_dstring_get_string(&ds)); error->next = NULL; sge_dstring_free(&ds); DPRINTF(("error: %s\n", error->message ? error->message : "")); if (et->first == NULL) { et->first = error; et->last = error; } else { et->last->next = error; et->last = error; } DEXIT; }
/****** uti/bootstrap/bootstrap_thread_local_init() ******************************* * NAME * bootstrap_thread_local_init() -- Initialize bootstrap state. * * SYNOPSIS * static void bootstrap_thread_local_init(sge_bootstrap_state_class_t* theState) * * FUNCTION * Initialize bootstrap state. * * INPUTS * bootstrap_state_t* theState - Pointer to bootstrap state structure. * * RESULT * static void - none * * NOTES * MT-NOTE: bootstrap_thread_local_init() is MT safe. * *******************************************************************************/ static void bootstrap_thread_local_init(sge_bootstrap_thread_local_t* theState) { memset(theState, 0, sizeof(sge_bootstrap_thread_local_t)); theState->original = (sge_bootstrap_state_class_t *)sge_malloc(sizeof(sge_bootstrap_state_class_t)); sge_bootstrap_state_class_init(theState->original, NULL); theState->current = theState->original; }
/****** sgeobj/var/var_list_set_sharedlib_path() ****************************** * NAME * var_list_set_sharedlib_path -- set shared lib path * * SYNOPSIS * void var_list_set_sharedlib_path(lList **varl); * * FUNCTION * Sets or replaces the shared lib path in the list of variables. * The SGE shared lib path is always set to the beginning of the * resulting shared lib path * (security, see var_get_sharedlib_path_name()) * * INPUTS * lList **varl - list of nment variables * * SEE ALSO * sgeobj/var/var_get_sharedlib_path_name() * sgeobj/var/var_list_set_string() * sgeobj/var/var_list_set_int() * sgeobj/var/var_list_set_sge_u32() ******************************************************************************/ void var_list_set_sharedlib_path(lList **varl) { char *sharedlib_path; char *sge_sharedlib_path; const char *sge_root = sge_get_root_dir(0, NULL, 0, 1); const char *sharedlib_path_name = var_get_sharedlib_path_name(); lListElem *sharedlib_elem = NULL; DENTER(TOP_LAYER, "set_sharedlib_path"); /* this is the SGE sharedlib path */ sge_sharedlib_path = sge_malloc(strlen(sge_root) + strlen("/lib/") + strlen(sge_get_arch()) + 1); sprintf(sge_sharedlib_path, "%s/lib/%s", sge_root, sge_get_arch()); /* if already in environment: extend by SGE sharedlib path, else set */ sharedlib_elem = lGetElemStr(*varl, VA_variable, sharedlib_path_name); if(sharedlib_elem != NULL) { const char *old_value = lGetString(sharedlib_elem, VA_value); if(old_value && strlen(old_value) > 0) { DPRINTF(("sharedlib path %s already set:\n", sharedlib_path_name)); sharedlib_path = sge_malloc(strlen(old_value) + 1 + strlen(sge_sharedlib_path) + 1); strcpy(sharedlib_path, sge_sharedlib_path); strcat(sharedlib_path, ":"); strcat(sharedlib_path, old_value); lSetString(sharedlib_elem, VA_value, sharedlib_path); sge_free(&sharedlib_path); } else { DPRINTF(("overwriting empty sharedlib path %s\n", sharedlib_path_name)); lSetString(sharedlib_elem, VA_value, sge_sharedlib_path); } } else { DPRINTF(("creating new sharedlib path %s\n", sharedlib_path_name)); sharedlib_elem = lAddElemStr(varl, VA_variable, sharedlib_path_name, VA_Type); lSetString(sharedlib_elem, VA_value, sge_sharedlib_path); } sge_free(&sge_sharedlib_path); DEXIT; }
void getenv_and_set(lListElem *ep, char *variable) { const char *env_value = NULL; char *new_env_value = NULL; char *a = NULL; char *b = NULL; int i, nchars; int newline_chars = 0; env_value = sge_getenv(variable); if (env_value == NULL) { lSetString(ep, VA_value, NULL); return; } /* * Any work to do? Check for any newline * character. */ a = strchr(env_value, '\n'); if (a == NULL) { /* * Nothing to do. Just leave it alone. */ lSetString(ep, VA_value, env_value); return; } /* * This is a multi-line environment variable. Allocate * new string and copy over, but without newline chars. */ nchars = strlen(env_value); a = (char *)env_value; newline_chars = 0; for (i = 0; i < nchars; i++) { if (*a == '\n') { newline_chars++; } a++; } new_env_value = sge_malloc(nchars - newline_chars + 1); a = new_env_value; b = (char *)env_value; for (i = 0; i < nchars; i++) { if (*b != '\n') { *a = *b; a++; } b++; } *a = '\0'; lSetString(ep, VA_value, new_env_value); sge_free(&new_env_value); return; }
int main(int argc, char *argv[]) { int num_objects; int num_names; int i; bool uh, nuh; if (argc != 1 && argc < 5) { usage(argv[0]); } /* initialize globals */ lInit(my_nmv); clk_tck = sysconf(_SC_CLK_TCK); /* JG: TODO: sge_sysconf? */ prof_mt_init(); /* we need random numbers */ srand(time(0)); if (argc == 1) { num_objects = 1000; num_names = 10; uh = true; nuh = true; } else { /* parse commandline options */ num_objects = atoi(argv[1]); num_names = atoi(argv[2]); uh = atoi(argv[3]) == 0 ? false : true; nuh = atoi(argv[4]) == 0 ? false : true; } /* create name array */ names = sge_malloc (num_names * sizeof(const char *)); /* build random names */ for (i = 0; i < num_names; i++) { const char *name = random_string(10); names[i] = name; } /* output header */ printf(HEADER_FORMAT, "uh ", "nuh", "create", "copy", "rau", "inu", "curo", "cnuro", "dru", "(objs)", "dinu", "(objs)", "mem(kB)"); /* do tests */ do_test(uh, nuh, num_objects, num_names); /* free names */ for (i = 0; i < num_names; i++) { sge_free(&(names[i])); } return EXIT_SUCCESS; }
sge_env_state_class_t *sge_env_state_class_create(const char *sge_root, const char *sge_cell, int sge_qmaster_port, int sge_execd_port, bool from_services, bool qmaster_internal, sge_error_class_t *eh) { sge_env_state_class_t *ret = (sge_env_state_class_t *)sge_malloc(sizeof(sge_env_state_class_t)); DENTER(TOP_LAYER, "sge_env_state_class_create"); if (!ret) { eh->error(eh, STATUS_EMALLOC, ANSWER_QUALITY_ERROR, MSG_MEMORY_MALLOCFAILED); DEXIT; return NULL; } ret->dprintf = sge_env_state_dprintf; ret->get_sge_root = get_sge_root; ret->get_sge_cell = get_sge_cell; ret->get_sge_qmaster_port = get_sge_qmaster_port; ret->get_sge_execd_port = get_sge_execd_port; ret->is_from_services = is_from_services; ret->is_qmaster_internal = is_qmaster_internal; ret->set_sge_root = set_sge_root; ret->set_sge_cell = set_sge_cell; ret->set_sge_qmaster_port = set_sge_qmaster_port; ret->set_sge_execd_port = set_sge_execd_port; ret->sge_env_state_handle = (sge_env_state_t*)sge_malloc(sizeof(sge_env_state_t)); if (ret->sge_env_state_handle == NULL) { eh->error(eh, STATUS_EMALLOC, ANSWER_QUALITY_ERROR, MSG_MEMORY_MALLOCFAILED); sge_env_state_class_destroy(&ret); DEXIT; return NULL; } memset(ret->sge_env_state_handle, 0, sizeof(sge_env_state_t)); if (!sge_env_state_setup(ret, sge_root, sge_cell, sge_qmaster_port, sge_execd_port, from_services, qmaster_internal, eh)) { sge_env_state_class_destroy(&ret); DEXIT; return NULL; } DEXIT; return ret; }
/****** get_bulk_jobid_string() ************************************************ * NAME * get_bulk_jobid_string() -- Turn the job id and parameters into a string * * SYNOPSIS * char *get_bulk_jobid_string(long job_id, int start, int end, int step) * * FUNCTION * Creates a string from the job id, start task, end task, and task step. * The return job id string must be freed by the caller. * * INPUT * long job_id - The job's id number * int start - The number of the first task in the job * int end - The number of the last task in the job * int step - The increment between job task numbers * * RESULT * static char * - The job id string * * NOTES * MT-NOTES: get_bulk_jobid_string() is MT safe *******************************************************************************/ static char *get_bulk_jobid_string(long job_id, int start, int end, int step) { char *jobid_str = sge_malloc(sizeof(char) * 1024); char *ret_str = NULL; sprintf(jobid_str, "%ld.%d-%d:%d", job_id, start, end, step); ret_str = strdup(jobid_str); sge_free(&jobid_str); return ret_str; }
sge_error_class_t* sge_error_class_create(void) { sge_error_class_t *ret = (sge_error_class_t*)sge_malloc(sizeof(sge_error_class_t)); if( ret == NULL ) { return NULL; } memset(ret,0,sizeof(sge_error_class_t)); ret->sge_error_handle = sge_malloc(sizeof(sge_error_t)); memset(ret->sge_error_handle, 0, sizeof(sge_error_t)); ret->has_error = sge_error_has_error; ret->has_quality = sge_error_has_quality; ret->has_type = sge_error_has_type; ret->error = sge_error_error; ret->verror = sge_error_verror; ret->clear = sge_error_class_clear; ret->iterator = sge_error_class_iterator; return ret; }
static sge_error_iterator_class_t* sge_error_iterator_class_create(sge_error_class_t *ec) { sge_error_iterator_class_t* ret = NULL; sge_error_iterator_t *elem = NULL; sge_error_t *et = (sge_error_t*)ec->sge_error_handle; DENTER(TOP_LAYER, "sge_error_message_class_create"); elem = (sge_error_iterator_t*)sge_malloc(sizeof(sge_error_iterator_t)); elem->current = et->first; elem->is_first_flag = true; ret = (sge_error_iterator_class_t*)sge_malloc(sizeof(sge_error_iterator_class_t)); ret->sge_error_iterator_handle = elem; ret->get_message = sge_error_iterator_get_message; ret->get_quality = sge_error_iterator_get_quality; ret->get_type = sge_error_iterator_get_type; ret->next = sge_error_iterator_next; DEXIT; return ret; }
static bool sge_bootstrap_state_class_init(sge_bootstrap_state_class_t *st, sge_error_class_t *eh) { DENTER(TOP_LAYER, "sge_bootstrap_state_class_init"); st->dprintf = sge_bootstrap_state_dprintf; st->get_admin_user = get_admin_user; st->get_default_domain = get_default_domain; st->get_ignore_fqdn = get_ignore_fqdn; st->get_spooling_method = get_spooling_method; st->get_spooling_lib = get_spooling_lib; st->get_spooling_params = get_spooling_params; st->get_binary_path = get_binary_path; st->get_qmaster_spool_dir = get_qmaster_spool_dir; st->get_security_mode = get_security_mode; st->get_job_spooling = get_job_spooling; st->get_listener_thread_count = get_listener_thread_count; st->get_worker_thread_count = get_worker_thread_count; st->get_scheduler_thread_count = get_scheduler_thread_count; st->get_jvm_thread_count = get_jvm_thread_count; st->set_admin_user = set_admin_user; st->set_default_domain = set_default_domain; st->set_ignore_fqdn = set_ignore_fqdn; st->set_spooling_method = set_spooling_method; st->set_spooling_lib = set_spooling_lib; st->set_spooling_params = set_spooling_params; st->set_binary_path = set_binary_path; st->set_qmaster_spool_dir = set_qmaster_spool_dir; st->set_security_mode = set_security_mode; st->set_job_spooling = set_job_spooling; st->set_listener_thread_count = set_listener_thread_count; st->set_worker_thread_count = set_worker_thread_count; st->set_scheduler_thread_count = set_scheduler_thread_count; st->set_jvm_thread_count = set_jvm_thread_count; st->sge_bootstrap_state_handle = sge_malloc(sizeof(sge_bootstrap_state_t)); if (st->sge_bootstrap_state_handle == NULL ) { if (eh != NULL) { eh->error(eh, STATUS_EMALLOC, ANSWER_QUALITY_ERROR, "%s", MSG_MEMORY_MALLOCFAILED); } DEXIT; return false; } memset(st->sge_bootstrap_state_handle, 0, sizeof(sge_bootstrap_state_t)); bootstrap_mt_init(); DEXIT; return true; }
/****** cull_state/cull_state_getspecific() ************************************ * NAME * cull_state_getspecific() -- Get thread local cull state * * SYNOPSIS * static cull_state_t* cull_state_getspecific(pthread_key_t aKey) * * FUNCTION * Return thread local cull state. * * If a given thread does call this function for the first time, no thread * local cull state is available for this particular thread. In this case the * thread local cull state is allocated and set. * * INPUTS * pthread_key_t aKey - Key for thread local cull state * * RESULT * static cull_state_t* - Pointer to thread local cull state * * NOTES * MT-NOTE: cull_state_getspecific() is MT safe * *******************************************************************************/ static cull_state_t* cull_state_getspecific(pthread_key_t aKey) { cull_state_t *cull_state = pthread_getspecific(aKey); if (cull_state == NULL) { int res = EINVAL; cull_state = (cull_state_t*)sge_malloc(sizeof(cull_state_t)); cull_state_init(cull_state); res = pthread_setspecific(cull_state_key, (const void*)cull_state); if (0 != res) { fprintf(stderr, "pthread_set_specific(%s) failed: %s\n", "cull_state_getspecific", strerror(res)); abort(); } } return cull_state; } /* cull_state_getspecific() */
/****** gdi/request_internal/sge_gdi_packet_create_base() ******************** * NAME * sge_gdi_packet_create_base() -- ??? * * SYNOPSIS * sge_gdi_packet_class_t * * sge_gdi_packet_create_base(lList **answer_list) * * FUNCTION * Creates a new GDI packet and initializes all base structure memebers * where necessary information is available. * * "uid", "gid", "user" and "group" memebers part of sge_gdi_packet_class_t * will not be initialized with this function. Instead * sge_gdi_packet_create() can be used or the function * sge_gdi_packet_initialize_auth_info() can be called afterwards. * * INPUTS * lList **answer_list - answer list in case of error * * RESULT * sge_gdi_packet_class_t * - new GDI packet * * NOTES * MT-NOTE: sge_gdi_packet_create_base() is MT safe * * SEE ALSO * gdi/request_internal/sge_gdi_packet_create() * gdi/request_internal/sge_gdi_packet_initialize_auth_info() ******************************************************************************/ sge_gdi_packet_class_t * sge_gdi_packet_create_base(lList **answer_list) { sge_gdi_packet_class_t *ret = NULL; DENTER(TOP_LAYER, "sge_gdi_packet_create_base"); ret = (sge_gdi_packet_class_t *) sge_malloc(sizeof(sge_gdi_packet_class_t)); if (ret != NULL) { int local_ret1; int local_ret2; local_ret1 = pthread_mutex_init(&(ret->mutex), NULL); local_ret2 = pthread_cond_init(&(ret->cond), NULL); if (local_ret1 == 0 && local_ret2 == 0) { ret->is_intern_request = false; ret->is_gdi_request = true; ret->is_handled = false; ret->id = 0; ret->host = NULL; ret->commproc = NULL; ret->commproc_id = 0; ret->version = GRM_GDI_VERSION; ret->first_task = NULL; ret->last_task = NULL; ret->auth_info = NULL; ret->next = NULL; memset(&(ret->pb), 0, sizeof(sge_pack_buffer)); } else { answer_list_add_sprintf(answer_list, STATUS_EMALLOC, ANSWER_QUALITY_ERROR, MSG_MEMORY_MALLOCFAILED); } } else { answer_list_add_sprintf(answer_list, STATUS_EMALLOC, ANSWER_QUALITY_ERROR, MSG_SGETEXT_NOMEM); } DRETURN(ret); }
/****** uti/log/log_buffer_getspecific() **************************************** * NAME * log_buffer_getspecific() -- Get thread local log state * * SYNOPSIS * static log_buffer_t* log_buffer_getspecific() * * FUNCTION * Return thread local log state. * * If a given thread does call this function for the first time, no thread * local log state is available for this particular thread. In this case the * thread local log state is allocated and set. * * RESULT * static log_buffer_t* - Pointer to thread local log state. * * NOTES * MT-NOTE: log_buffer_getspecific() is MT safe * *******************************************************************************/ static log_buffer_t* log_buffer_getspecific(void) { log_buffer_t *buf = NULL; int res = -1; pthread_once(&log_buffer_once, log_buffer_once_init); if ((buf = pthread_getspecific(log_buffer_key)) != NULL) { return buf; } buf = (log_buffer_t*)sge_malloc(sizeof(log_buffer_t)); memset((void*)(buf), 0, sizeof(log_buffer_t)); res = pthread_setspecific(log_buffer_key, (const void*)buf); if (0 != res) { fprintf(stderr, "pthread_set_specific(%s) failed: %s\n", "log_buffer_getspecific", strerror(res)); abort(); } return buf; } /* log_buffer_getspecific() */
/****** 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[MAX_STRING_SIZE]; char *file = NULL; DENTER (TOP_LAYER, "get_cwd_defaults_file_name"); if (!getcwd(cwd, sizeof(cwd))) { snprintf(str, sizeof(str), SFNMAX, MSG_FILE_CANTREADCURRENTWORKINGDIR); answer_list_add(answer_list, str, STATUS_EDISK, ANSWER_QUALITY_ERROR); } file = sge_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); }
/****** uti/log/log_context_getspecific() **************************************** * NAME * log_context_getspecific() -- Get thread local log context * * SYNOPSIS * static log_context_t* log_context_getspecific() * * FUNCTION * Return thread local log context. * * If a given thread does call this function for the first time, no thread * local log state is available for this particular thread. In this case the * thread local log state is allocated and set. * * RESULT * static log_context_t* - Pointer to thread local log context. * * NOTES * MT-NOTE: log_context_getspecific() is MT safe * *******************************************************************************/ static log_context_t* log_context_getspecific(void) { log_context_t *myctx = NULL; int res = -1; pthread_once(&log_context_once, log_context_once_init); if ((myctx = pthread_getspecific(log_context_key)) != NULL) { return myctx; } myctx = (log_context_t*)sge_malloc(sizeof(log_context_t)); if (myctx != NULL) { myctx->context = NULL; } res = pthread_setspecific(log_context_key, (const void*)myctx); if (0 != res) { fprintf(stderr, "pthread_set_specific(%s) failed: %s\n", "log_context_getspecific", strerror(res)); abort(); } return myctx; } /* log_context_getspecific() */
static sge_gdi_task_class_t * sge_gdi_task_create(sge_gdi_packet_class_t * packet, lList **answer_list, u_long32 target, u_long32 command, lList **lp, lList **a_list, lCondition **condition, lEnumeration **enumeration, bool do_copy, bool do_verify) { sge_gdi_task_class_t *task = NULL; DENTER(TOP_LAYER, "sge_gdi_task_create"); task = (sge_gdi_task_class_t *) sge_malloc(sizeof(sge_gdi_task_class_t)); if (task != NULL) { task->id = ((packet->last_task != NULL) ? (packet->last_task->id + 1) : 1); task->command = command; task->target = target; task->next = NULL; task->do_select_pack_simultaneous = false; if (do_copy) { if (enumeration != NULL && *enumeration != NULL) { task->data_list = (((lp != NULL) && (*lp != NULL)) ? lSelect("", *lp, NULL, *enumeration) : NULL); } else { task->data_list = (((lp != NULL) && (*lp != NULL)) ? lCopyList("", *lp) : NULL); } task->answer_list = (((a_list != NULL) && (*a_list != NULL)) ? lCopyList("", *a_list) : NULL); task->condition = (((condition != NULL) && (*condition != NULL)) ? lCopyWhere(*condition) : NULL); task->enumeration = (((enumeration != NULL) && (*enumeration != NULL)) ? lCopyWhat(*enumeration) : NULL); } else { if ((lp != NULL) && (*lp != NULL)) { task->data_list = *lp; *lp = NULL; } else { task->data_list = NULL; } if ((a_list != NULL) && (*a_list != NULL)) { task->answer_list = *a_list; *a_list = NULL; } else { task->answer_list = NULL; } if ((condition != NULL) && (*condition != NULL)) { task->condition = *condition; *condition = NULL; } else { task->condition = NULL; } if ((enumeration != NULL) && (*enumeration != NULL)) { task->enumeration = *enumeration; *enumeration = NULL; } else { task->enumeration = NULL; } } if (do_verify && !sge_gdi_task_verify(task, answer_list)) { if (do_copy == true) { lFreeList(&(task->data_list)); lFreeList(&(task->answer_list)); lFreeWhere(&(task->condition)); lFreeWhat(&(task->enumeration)); } else { task->data_list = NULL; task->answer_list = NULL; task->condition = NULL; task->enumeration = NULL; } sge_gdi_task_free(&task); } } else { answer_list_add_sprintf(answer_list, STATUS_EMALLOC, ANSWER_QUALITY_ERROR, MSG_MEMORY_MALLOCFAILED); } DRETURN(task); }
static int check_config(lList **alpp, lListElem *conf) { lListElem *ep; const char *name, *value; const char *conf_name; DENTER(TOP_LAYER, "check_config"); conf_name = lGetHost(conf, CONF_name); for_each(ep, lGetList(conf, CONF_entries)) { name = lGetString(ep, CF_name); value = lGetString(ep, CF_value); if (name == NULL) { ERROR((SGE_EVENT, MSG_CONF_NAMEISNULLINCONFIGURATIONLISTOFX_S, conf_name)); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } if (value == NULL) { ERROR((SGE_EVENT, MSG_CONF_VALUEISNULLFORATTRXINCONFIGURATIONLISTOFY_SS, name, conf_name)); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } if (!strcmp(name, "loglevel")) { u_long32 tmp_uval; if (sge_parse_loglevel_val(&tmp_uval, value) != 1) { ERROR((SGE_EVENT, MSG_CONF_GOTINVALIDVALUEXFORLOGLEVEL_S, value)); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } } else if (strcmp(name, "jsv_url") == 0) { if (strcasecmp("none", value) != 0) { dstring input = DSTRING_INIT; dstring type = DSTRING_INIT; dstring user = DSTRING_INIT; dstring path = DSTRING_INIT; bool lret = true; sge_dstring_append(&input, value); lret = jsv_url_parse(&input, alpp, &type, &user, &path, false); sge_dstring_free(&input); sge_dstring_free(&type); sge_dstring_free(&user); sge_dstring_free(&path); if (!lret) { /* answer is written by jsv_url_parse */ DRETURN(STATUS_EEXIST); } } } else if (!strcmp(name, "shell_start_mode")) { if ((strcasecmp("unix_behavior", value) != 0) && (strcasecmp("posix_compliant", value) != 0) && (strcasecmp("script_from_stdin", value) != 0) ) { ERROR((SGE_EVENT, MSG_CONF_GOTINVALIDVALUEXFORSHELLSTARTMODE_S, value)); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } } else if (!strcmp(name, "shell")) { if (!path_verify(name, alpp, "shell", true)) { ERROR((SGE_EVENT, MSG_CONF_GOTINVALIDVALUEXFORSHELL_S, value)); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } } else if (!strcmp(name, "load_report_time")) { /* do not allow infinity entry for load_report_time */ if (strcasecmp(value, "infinity") == 0) { ERROR((SGE_EVENT, MSG_CONF_INFNOTALLOWEDFORATTRXINCONFLISTOFY_SS, name, conf_name)); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } } else if (!strcmp(name, "max_unheard")) { /* do not allow infinity entry */ if (strcasecmp(value,"infinity") == 0) { ERROR((SGE_EVENT, MSG_CONF_INFNOTALLOWEDFORATTRXINCONFLISTOFY_SS, name, conf_name)); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } } else if (!strcmp(name, "admin_user")) { struct passwd pw_struct; char *buffer; int size; size = get_pw_buffer_size(); buffer = sge_malloc(size); if (strcasecmp(value, "none") && !sge_getpwnam_r(value, &pw_struct, buffer, size)) { ERROR((SGE_EVENT, MSG_CONF_GOTINVALIDVALUEXASADMINUSER_S, value)); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); sge_free(&buffer); DRETURN(STATUS_EEXIST); } sge_free(&buffer); } else if (!strcmp(name, "user_lists")||!strcmp(name, "xuser_lists")) { lList *tmp = NULL; int ok; /* parse just for .. */ if (lString2ListNone(value, &tmp, US_Type, US_name, " \t,")) { ERROR((SGE_EVENT, MSG_CONF_FORMATERRORFORXINYCONFIG_SS, name, conf_name)); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } /* .. checking userset names */ ok = (userset_list_validate_acl_list(tmp, alpp) == STATUS_OK); lFreeList(&tmp); if (!ok) { DRETURN(STATUS_EEXIST); } } else if (!strcmp(name, "projects") || !strcmp(name, "xprojects")) { lList *tmp = NULL; int ok=1; /* parse just for .. */ if (lString2ListNone(value, &tmp, PR_Type, PR_name, " \t,")) { ERROR((SGE_EVENT, MSG_CONF_FORMATERRORFORXINYCONFIG_SS, name, conf_name)); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } /* .. checking project names */ ok = (verify_project_list(alpp, tmp, *object_type_get_master_list(SGE_TYPE_PROJECT), name, "configuration", conf_name)==STATUS_OK); lFreeList(&tmp); if (!ok) { DRETURN(STATUS_EEXIST); } } else if (!strcmp(name, "prolog") || !strcmp(name, "epilog") || !strcmp(name, "mailer")) { if (strcasecmp(value, "none")) { const char *t, *script = value; /* skip user name */ if ((t = strpbrk(script, "@ ")) && *t == '@') script = &t[1]; /* force use of absolute paths if string <> none */ if (script[0] != '/' ) { ERROR((SGE_EVENT, MSG_CONF_THEPATHGIVENFORXMUSTSTARTWITHANY_S, name)); answer_list_add(alpp, SGE_EVENT, STATUS_EUNKNOWN, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } /* ensure that variables are valid */ if (replace_params(script, NULL, 0, prolog_epilog_variables)) { ERROR((SGE_EVENT, MSG_CONF_PARAMETERXINCONFIGURATION_SS, name, err_msg)); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } } } else if (!strcmp(name, "auto_user_oticket") || !strcmp(name, "auto_user_fshare")) { u_long32 uval = 0; if (!extended_parse_ulong_val(NULL, &uval, TYPE_INT, value, NULL, 0, 0, true)) { ERROR((SGE_EVENT, MSG_CONF_FORMATERRORFORXINYCONFIG_SS, name, value ? value : "(NULL)")); answer_list_add(alpp, SGE_EVENT, STATUS_EEXIST, ANSWER_QUALITY_ERROR); DRETURN(STATUS_EEXIST); } } /* * check paths, see also CR 6506580. * The following must be none or a valid absolute path: * - load_sensor * - set_token_cmd * - pag_cmd * - shepherd_cmd * * The following must be a valid absolute path: * - mailer * - xterm * - *_daemon, may also be "builtin" */ else if (strcmp(name, "set_token_cmd") == 0 || strcmp(name, "pag_cmd") == 0 || strcmp(name, "shepherd_cmd") == 0) { if (strcasecmp(value, "none") != 0) { if (!path_verify(value, alpp, name, true)) { answer_list_log(alpp, false, false); DRETURN(STATUS_EEXIST); } } } else if (strcmp(name, "mailer") == 0 || strcmp(name, "xterm") == 0) { if (!path_verify(value, alpp, name, true)) { answer_list_log(alpp, false, false); DRETURN(STATUS_EEXIST); } } else if (strcmp(name, "qlogin_daemon") == 0 || strcmp(name, "rlogin_daemon") == 0 || strcmp(name, "rsh_daemon") == 0) { if (strcasecmp(value, "builtin") != 0) { if (!path_verify(value, alpp, name, true)) { answer_list_log(alpp, false, false); DRETURN(STATUS_EEXIST); } } } /* load_sensor is a comma separated list of scripts */ else if (strcmp(name, "load_sensor") == 0 && strcasecmp(value, "none") != 0) { struct saved_vars_s *context = NULL; const char *path = sge_strtok_r(value, ",", &context); do { if (!path_verify(path, alpp, name, true)) { answer_list_log(alpp, false, false); sge_free_saved_vars(context); DRETURN(STATUS_EEXIST); } } while ((path = sge_strtok_r(NULL, ",", &context)) != NULL); sge_free_saved_vars(context); } }
/* * TODO: CLEANUP * * This function is DEPRECATED and should be removed with the next * major release. * * This function can't be used in multi threaded environments because it * might cause a deadlock in the executing qmaster thread. * Use sge_peopen_r() instead. */ pid_t sge_peopen(const char *shell, int login_shell, const char *command, const char *user, char **env, FILE **fp_in, FILE **fp_out, FILE **fp_err, bool null_stderr) { pid_t pid; int pipefds[3][2]; const char *could_not = MSG_SYSTEM_EXECBINSHFAILED; const char *not_root = MSG_SYSTEM_NOROOTRIGHTSTOSWITCHUSER; int i; char arg0[256]; char err_str[256]; #if !(defined(WIN32) || defined(INTERIX)) /* var not needed */ int res; #endif /* WIN32 */ uid_t myuid; DENTER(TOP_LAYER, "sge_peopen"); /* open pipes - close on failure */ for (i=0; i<3; i++) { if (pipe(pipefds[i]) != 0) { while (--i >= 0) { close(pipefds[i][0]); close(pipefds[i][1]); } ERROR((SGE_EVENT, MSG_SYSTEM_FAILOPENPIPES_SS, command, strerror(errno))); DEXIT; return -1; } } #if defined(SOLARIS) pid = sge_smf_contract_fork(err_str, 256); #else pid = fork(); #endif if (pid == 0) { /* child */ int keep_open[6]; keep_open[0] = 0; keep_open[1] = 1; keep_open[2] = 2; keep_open[3] = pipefds[0][0]; keep_open[4] = pipefds[1][1]; keep_open[5] = pipefds[2][1]; sge_close_all_fds(keep_open, 6); /* shall we redirect stderr to /dev/null? */ if (null_stderr) { /* open /dev/null */ int fd = open("/dev/null", O_WRONLY); if (fd == -1) { sprintf(err_str, MSG_ERROROPENINGFILEFORWRITING_SS, "/dev/null", strerror(errno)); sprintf(err_str, "\n"); write(2, err_str, strlen(err_str)); SGE_EXIT(NULL, 1); } /* set stderr to /dev/null */ close(2); dup(fd); /* we don't need the stderr the pipe - close it */ close(pipefds[2][1]); } else { /* redirect stderr to the pipe */ close(2); dup(pipefds[2][1]); } /* redirect stdin and stdout to the pipes */ close(0); close(1); dup(pipefds[0][0]); dup(pipefds[1][1]); if (user) { struct passwd *pw; struct passwd pw_struct; char *buffer; int size; size = get_pw_buffer_size(); buffer = sge_malloc(size); if (!(pw=sge_getpwnam_r(user, &pw_struct, buffer, size))) { sprintf(err_str, MSG_SYSTEM_NOUSERFOUND_SS , user, strerror(errno)); sprintf(err_str, "\n"); write(2, err_str, strlen(err_str)); FREE(buffer); SGE_EXIT(NULL, 1); } myuid = geteuid(); if (myuid != pw->pw_uid) { /* Only change user if we differ from the wanted user */ if(myuid != SGE_SUPERUSER_UID) { write(2, not_root, sizeof(not_root)); FREE(buffer); SGE_EXIT(NULL, 1); } sprintf(err_str, "%s %d\n", pw->pw_name, (int)pw->pw_gid); write(2, err_str, strlen(err_str)); #if !(defined(WIN32) || defined(INTERIX)) /* initgroups not called */ res = initgroups(pw->pw_name,pw->pw_gid); # if defined(SVR3) || defined(sun) if (res < 0) # else if (res) # endif { sprintf(err_str, MSG_SYSTEM_INITGROUPSFORUSERFAILED_ISS , res, user, strerror(errno)); sprintf(err_str, "\n"); write(2, err_str, strlen(err_str)); FREE(buffer); SGE_EXIT(NULL, 1); } #endif /* WIN32 */ if (setuid(pw->pw_uid)) { sprintf(err_str, MSG_SYSTEM_SWITCHTOUSERFAILED_SS , user, strerror(errno)); sprintf(err_str, "\n"); write(2, err_str, strlen(err_str)); FREE(buffer); SGE_EXIT(NULL, 1); } } addenv("HOME", pw->pw_dir); addenv("SHELL", pw->pw_shell); addenv("USER", pw->pw_name); addenv("LOGNAME", pw->pw_name); addenv("PATH", SGE_DEFAULT_PATH); FREE(buffer); } if (login_shell) strcpy(arg0, "-"); else strcpy(arg0, ""); strcat(arg0, shell); if (env) for(; *env; env++) putenv(*env); execlp(shell, arg0, "-c", command, NULL); write(2, could_not, sizeof(could_not)); SGE_EXIT(NULL, 1); } if (pid < 0) { for (i=0; i<3; i++) { close(pipefds[i][0]); close(pipefds[i][1]); } #if defined(SOLARIS) if (pid < -1 && err_str) { ERROR((SGE_EVENT, MSG_SMF_FORK_FAILED_SS, "sge_peopen()", err_str)); } #endif /* fork could have failed, report it */ ERROR((SGE_EVENT, MSG_SMF_FORK_FAILED_SS, "sge_peopen()", strerror(errno))); DEXIT; return -1; } /* close the childs ends of the pipes */ close(pipefds[0][0]); close(pipefds[1][1]); close(pipefds[2][1]); /* return filehandles for stdin and stdout */ *fp_in = fdopen(pipefds[0][1], "a"); *fp_out = fdopen(pipefds[1][0], "r"); /* is stderr redirected to /dev/null? */ if (null_stderr) { /* close the pipe and return NULL as filehandle */ close(pipefds[2][0]); *fp_err = NULL; } else { /* return filehandle for stderr */ *fp_err = fdopen(pipefds[2][0], "r"); } DEXIT; return pid; }
/****** uti/stdio/sge_peopen() ************************************************ * NAME * sge_peopen_r() -- Advanced popen() * * SYNOPSIS * pid_t sge_peopen_r(const char *shell, int login_shell, * const char *command, const char *user, * char **env, FILE **fp_in, FILE **fp_out, * FILE **fp_err) * * FUNCTION * Advanced popen() with additional parameters: * - free shell usage * - login shell if wanted * - user under which to start (for root only) * - stdin and stderr file pointers * - wait for exactly the process we started * File descriptors have to be closed with sge_peclose(). * * This function is reentrant as long as env is not provided to * this function. This means that the function can be used in * multi thread processed as long as env is not used. * * INPUTS * const char *shell - which shell to use * int login_shell - make it a login shell? * const char *command - name of the program * const char *user - user under which to start (for root only) * char **env - env variables to add to child * FILE **fp_in - file input stream * FILE **fp_out - file output stream * FILE **fp_err - file error stream * * RESULT * pid_t - process id * * NOTES * MT-NOTE: sge_peopen() is MT safe * * DO NOT ADD ASYNC SIGNAL UNSAFE FUNCTIONS BETWEEN FORK AND EXEC * DUE TO THE FACT THAT THIS FUNCTION WILL BE USED IN QMASTER * (MULTITHREADED ENVIRONMENT) THIS MIGHT CAUSE A DEADLOCK * IN A MASTER THREAD. * * SEE ALSO * uti/stdio/sge_peclose() ******************************************************************************/ pid_t sge_peopen_r(const char *shell, int login_shell, const char *command, const char *user, char **env, FILE **fp_in, FILE **fp_out, FILE **fp_err, bool null_stderr) { pid_t pid; int pipefds[3][2]; int i; char arg0[256]; #if defined(SOLARIS) char err_str[256]; #endif struct passwd *pw = NULL; uid_t myuid; uid_t tuid; DENTER(TOP_LAYER, "sge_peopen_r"); if (sge_has_admin_user()) { sge_switch2start_user(); } myuid = geteuid(); tuid = myuid; /* * open pipes - close on failure */ for (i = 0; i < 3; i++) { if (pipe(pipefds[i]) != 0) { while (--i >= 0) { close(pipefds[i][0]); close(pipefds[i][1]); } ERROR((SGE_EVENT, MSG_SYSTEM_FAILOPENPIPES_SS, command, strerror(errno))); if (sge_has_admin_user()) { sge_switch2admin_user(); } DRETURN(-1); } } /* * set arg0 for exec call correctly to that * either a normal shell or a login shell will be started */ if (login_shell) { strcpy(arg0, "-"); } else { strcpy(arg0, ""); } strcat(arg0, shell); DPRINTF(("arg0 = %s\n", arg0)); DPRINTF(("arg1 = -c\n")); DPRINTF(("arg2 = %s\n", command)); /* * prepare the change of the user which might be done after fork() * if a user name is provided. * * this has to be done before the fork() afterwards it might cause * a deadlock of the child because getpwnam() is not async-thread safe. */ if (user) { struct passwd pw_struct; int size = get_pw_buffer_size(); char *buffer = sge_malloc(size); /* * get information about the target user */ if (buffer != NULL) { pw = sge_getpwnam_r(user, &pw_struct, buffer, size); if (pw == NULL) { ERROR((SGE_EVENT, MSG_SYSTEM_NOUSERFOUND_SS, user, strerror(errno))); FREE(buffer); if (sge_has_admin_user()) { sge_switch2admin_user(); } DRETURN(-1); } } else { ERROR((SGE_EVENT, MSG_UTI_MEMPWNAM)); FREE(buffer); if (sge_has_admin_user()) { sge_switch2admin_user(); } DRETURN(-1); } DPRINTF(("was able to resolve user\n")); /* * only prepare change of user if target user is different from current one */ if (myuid != pw->pw_uid) { #if !(defined(WIN32) || defined(INTERIX)) /* var not needed */ int res; #endif if (myuid != SGE_SUPERUSER_UID) { DPRINTF(("only root is allowed to switch to a different user\n")); ERROR((SGE_EVENT, MSG_SYSTEM_NOROOTRIGHTSTOSWITCHUSER)); FREE(buffer); DRETURN(-2); } DPRINTF(("Before initgroups\n")); #if !(defined(WIN32) || defined(INTERIX)) /* initgroups not called */ res = initgroups(pw->pw_name, pw->pw_gid); # if defined(SVR3) || defined(sun) if (res < 0) # else if (res) # endif { ERROR((SGE_EVENT, MSG_SYSTEM_INITGROUPSFORUSERFAILED_ISS, res, user, strerror(errno))); FREE(buffer); SGE_EXIT(NULL, 1); } DPRINTF(("Initgroups was successful\n")); #endif /* WIN32 */ } DPRINTF(("user = %s\n", user)); DPRINTF(("myuid = %d\n", (int)myuid)); if (pw != NULL) { tuid = pw->pw_uid; DPRINTF(("target uid = %d\n", (int)tuid)); } FREE(buffer); } DPRINTF(("Now process will fork\n")); #if defined(SOLARIS) pid = sge_smf_contract_fork(err_str, 256); #else pid = fork(); #endif /* * in the child pid is 0 */ if (pid == 0) { /* * close all fd's except that ones mentioned in keep_open */ int keep_open[6]; keep_open[0] = 0; keep_open[1] = 1; keep_open[2] = 2; keep_open[3] = pipefds[0][0]; keep_open[4] = pipefds[1][1]; keep_open[5] = pipefds[2][1]; sge_close_all_fds(keep_open, 6); /* * shall we redirect stderr to /dev/null? Then * - open "/dev/null" * - set stderr to "dev/null" * - close the stderr-pipe * otherwise * - redirect stderr to the pipe */ if (null_stderr) { int fd = open("/dev/null", O_WRONLY); if (fd != -1) { close(2); dup(fd); close(pipefds[2][1]); } else { SGE_EXIT(NULL, 1); } } else { close(2); dup(pipefds[2][1]); } /* * redirect stdin and stdout to the pipes */ close(0); close(1); dup(pipefds[0][0]); dup(pipefds[1][1]); if (pw != NULL) { int lret = setuid(tuid); if (lret) { SGE_EXIT(NULL, 1); } } /* * set the environment if we got one as argument */ if (env != NULL) { if (pw != NULL) { addenv("HOME", pw->pw_dir); addenv("SHELL", pw->pw_shell); addenv("USER", pw->pw_name); addenv("LOGNAME", pw->pw_name); } addenv("PATH", SGE_DEFAULT_PATH); for(; *env; env++) { putenv(*env); } } execlp(shell, arg0, "-c", command, NULL); } if (pid < 0) { for (i=0; i<3; i++) { close(pipefds[i][0]); close(pipefds[i][1]); } #if defined(SOLARIS) if (pid < -1 && err_str) { ERROR((SGE_EVENT, MSG_SMF_FORK_FAILED_SS, "sge_peopen()", err_str)); } #endif if (sge_has_admin_user()) { sge_switch2admin_user(); } DRETURN(-1); } /* close the childs ends of the pipes */ close(pipefds[0][0]); close(pipefds[1][1]); close(pipefds[2][1]); /* return filehandles for stdin and stdout */ *fp_in = fdopen(pipefds[0][1], "a"); *fp_out = fdopen(pipefds[1][0], "r"); /* is stderr redirected to /dev/null? */ if (null_stderr) { /* close the pipe and return NULL as filehandle */ close(pipefds[2][0]); *fp_err = NULL; } else { /* return filehandle for stderr */ *fp_err = fdopen(pipefds[2][0], "r"); } if (sge_has_admin_user()) { sge_switch2admin_user(); } DRETURN(pid); }
/****** Interactive/qrsh/startJob() *************************************** * * NAME * startJob() -- start a shell with commands to execute * * SYNOPSIS * static int startJob(char *command, char *wrapper, int noshell); * * FUNCTION * Starts the commands and arguments to be executed as * specified in parameter <command>. * If the parameter noshell is set to 1, the command is directly called * by exec. * If a wrapper is specified (parameter wrapper, set by environment * variable QRSH_WRAPPER), this wrapper is called and is passed the * command to execute as commandline parameters. * If neither noshell nor wrapper is set, a users login shell is called * with the parameters -c <command>. * The child process creates an own process group. * The pid of the child process is written to a pid file in $TMPDIR. * * INPUTS * command - commandline to be executed * wrapper - name and path of a wrapper script * noshell - if != 0, call the command directly without shell * * RESULT * status of the child process after it terminated * or EXIT_FAILURE, if the process of starting the child * failed because of one of the following error situations: * - fork failed * - the pid of the child process cannot be written to pid file * - the name of actual user cannot be determined * - info about the actual user cannot be determined (getpwnam) * - necessary memory cannot be allocated * - executing the shell failed * * SEE ALSO * Interactive/qrsh/write_pid_file() * Interactive/qrsh/split_command() * Interactive/qrsh/join_command() * **************************************************************************** */ static int startJob(char *command, char *wrapper, int noshell) { child_pid = fork(); if(child_pid == -1) { qrsh_error(MSG_QRSH_STARTER_CANNOTFORKCHILD_S, strerror(errno)); return EXIT_FAILURE; } if(child_pid) { /* parent */ int status; #if defined(LINUX) int ttyfd; #endif signal(SIGINT, forward_signal); signal(SIGQUIT, forward_signal); signal(SIGTERM, forward_signal); /* preserve pseudo terminal */ #if defined(LINUX) ttyfd = open("/dev/tty", O_RDWR); if (ttyfd != -1) { tcsetpgrp(ttyfd, child_pid); close(ttyfd); } #endif while(waitpid(child_pid, &status, 0) != child_pid && errno == EINTR); return(status); } else { /* child */ char *buffer = NULL; int size; struct passwd pw_struct; char *shell = NULL; char *userName = NULL; int argc = 0; const char **args = NULL; char *cmd = NULL; int cmdargc; char **cmdargs = NULL; int i; if(!write_pid_file(getpid())) { exit(EXIT_FAILURE); } cmdargc = split_command(command, &cmdargs); if(cmdargc == 0) { qrsh_error(MSG_QRSH_STARTER_INVALIDCOMMAND); exit(EXIT_FAILURE); } if(!noshell) { struct passwd *pw = NULL; if((userName = search_conf_val("job_owner")) == NULL) { qrsh_error(MSG_QRSH_STARTER_CANNOTGETLOGIN_S, strerror(errno)); exit(EXIT_FAILURE); } size = get_pw_buffer_size(); buffer = sge_malloc(size); if ((pw = sge_getpwnam_r(userName, &pw_struct, buffer, size)) == NULL) { qrsh_error(MSG_QRSH_STARTER_CANNOTGETUSERINFO_S, strerror(errno)); exit(EXIT_FAILURE); } shell = pw->pw_shell; if(shell == NULL) { qrsh_error(MSG_QRSH_STARTER_CANNOTDETERMSHELL_S, "/bin/sh"); shell = "/bin/sh"; } } if((args = malloc((cmdargc + 3) * sizeof(char *))) == NULL) { qrsh_error(MSG_QRSH_STARTER_MALLOCFAILED_S, strerror(errno)); exit(EXIT_FAILURE); } if(wrapper == NULL) { if(noshell) { cmd = cmdargs[0]; for(i = 0; i < cmdargc; i++) { args[argc++] = cmdargs[i]; } } else { cmd = shell; args[argc++] = sge_basename(shell, '/'); args[argc++] = "-c"; args[argc++] = join_command(cmdargc, cmdargs); } } else { cmd = wrapper; args[argc++] = sge_basename(wrapper, '/'); for(i = 0; i < cmdargc; i++) { args[argc++] = cmdargs[i]; } } args[argc++] = NULL; #if 0 { /* debug code */ int i; fflush(stdout) ; fflush(stderr); printf("qrsh_starter: executing %s\n", cmd); for(i = 1; args[i] != NULL; i++) { printf("args[%d] = %s\n", i, args[i]); } printf("\n"); fflush(stdout) ; fflush(stderr); } #endif SETPGRP; execvp(cmd, (char *const *)args); /* exec failed */ fprintf(stderr, MSG_QRSH_STARTER_EXECCHILDFAILED_S, args[0], strerror(errno)); fprintf(stderr, "\n"); exit(EXIT_FAILURE); } /* will never be reached */ return EXIT_FAILURE; }
bool sge_parse_qrsub(sge_gdi_ctx_class_t *ctx, lList *pcmdline, lList **alpp, lListElem **ar) { lListElem *ep = NULL, *next_ep = NULL; lList *lp = NULL; DENTER(TOP_LAYER, "sge_parse_qrsub"); /* -help print this help */ if ((ep = lGetElemStr(pcmdline, SPA_switch, "-help"))) { lRemoveElem(pcmdline, &ep); sge_usage(QRSUB, stdout); DEXIT; SGE_EXIT((void **)&ctx, 0); } /* -a date_time start time in [[CC]YY]MMDDhhmm[.SS] SGE_ULONG */ while ((ep = lGetElemStr(pcmdline, SPA_switch, "-a"))) { lSetUlong(*ar, AR_start_time, lGetUlong(ep, SPA_argval_lUlongT)); lRemoveElem(pcmdline, &ep); } /* -e date_time end time in [[CC]YY]MMDDhhmm[.SS] SGE_ULONG*/ while ((ep = lGetElemStr(pcmdline, SPA_switch, "-e"))) { lSetUlong(*ar, AR_end_time, lGetUlong(ep, SPA_argval_lUlongT)); lRemoveElem(pcmdline, &ep); } /* -d time duration in TIME format SGE_ULONG */ while ((ep = lGetElemStr(pcmdline, SPA_switch, "-d"))) { lSetUlong(*ar, AR_duration, lGetUlong(ep, SPA_argval_lUlongT)); lRemoveElem(pcmdline, &ep); } /* -w e/v validate availability of AR request, default e SGE_ULONG */ while ((ep = lGetElemStr(pcmdline, SPA_switch, "-w"))) { lSetUlong(*ar, AR_verify, lGetInt(ep, SPA_argval_lIntT)); lRemoveElem(pcmdline, &ep); } /* -N name AR name SGE_STRING */ while ((ep = lGetElemStr(pcmdline, SPA_switch, "-N"))) { lSetString(*ar, AR_name, lGetString(ep, SPA_argval_lStringT)); lRemoveElem(pcmdline, &ep); } /* -A account_string AR name in accounting record SGE_STRING */ while ((ep = lGetElemStr(pcmdline, SPA_switch, "-A"))) { lSetString(*ar, AR_account, lGetString(ep, SPA_argval_lStringT)); lRemoveElem(pcmdline, &ep); } /* -l resource_list request the given resources SGE_LIST */ parse_list_simple(pcmdline, "-l", *ar, AR_resource_list, 0, 0, FLG_LIST_APPEND); centry_list_remove_duplicates(lGetList(*ar, AR_resource_list)); /* -u wc_user access list SGE_LIST */ /* -u ! wc_user TBD: Think about eval_expression support in compare allowed and excluded lists */ parse_list_simple(pcmdline, "-u", *ar, AR_acl_list, ARA_name, 0, FLG_LIST_MERGE); /* -u ! list separation */ lp = lGetList(*ar, AR_acl_list); next_ep = lFirst(lp); while ((ep = next_ep)) { bool is_xacl = false; const char *name = lGetString(ep, ARA_name); next_ep = lNext(ep); if (name[0] == '!') { /* move this element to xacl_list */ is_xacl = true; name++; } if (!is_hgroup_name(name)) { struct passwd *pw; struct passwd pw_struct; char *buffer; int size; stringT group; size = get_pw_buffer_size(); buffer = sge_malloc(size); pw = sge_getpwnam_r(name, &pw_struct, buffer, size); if (pw == NULL) { answer_list_add_sprintf(alpp, STATUS_EUNKNOWN, ANSWER_QUALITY_ERROR, MSG_USER_XISNOKNOWNUSER_S, name); FREE(buffer); DRETURN(false); } sge_gid2group(pw->pw_gid, group, MAX_STRING_SIZE, MAX_NIS_RETRIES); lSetString(ep, ARA_group, group); FREE(buffer); } if (is_xacl) { lListElem *new_ep = lAddSubStr(*ar, ARA_name, name, AR_xacl_list, ARA_Type); lSetString(new_ep, ARA_group, lGetString(ep, ARA_group)); lRemoveElem(lp, &ep); } } /* -q wc_queue_list reserve in queue(s) SGE_LIST */ parse_list_simple(pcmdline, "-q", *ar, AR_queue_list, 0, 0, FLG_LIST_APPEND); /* -pe pe_name slot_range reserve slot range for parallel jobs */ while ((ep = lGetElemStr(pcmdline, SPA_switch, "-pe"))) { lSetString(*ar, AR_pe, lGetString(ep, SPA_argval_lStringT)); /* SGE_STRING, */ lSwapList(*ar, AR_pe_range, ep, SPA_argval_lListT); /* SGE_LIST */ lRemoveElem(pcmdline, &ep); } /* AR_master_queue_list -masterq wc_queue_list, SGE_LIST bind master task to queue(s) */ parse_list_simple(pcmdline, "-masterq", *ar, AR_master_queue_list, 0, 0, FLG_LIST_APPEND); /* -ckpt ckpt-name reserve in queue with ckpt method SGE_STRING */ while ((ep = lGetElemStr(pcmdline, SPA_switch, "-ckpt"))) { lSetString(*ar, AR_checkpoint_name, lGetString(ep, SPA_argval_lStringT)); lRemoveElem(pcmdline, &ep); } /* -m b/e/a/n define mail notification events SGE_ULONG */ while ((ep = lGetElemStr(pcmdline, SPA_switch, "-m"))) { u_long32 ul; u_long32 old_mail_opts; ul = lGetInt(ep, SPA_argval_lIntT); if ((ul & NO_MAIL)) { lSetUlong(*ar, AR_mail_options, 0); } else { old_mail_opts = lGetUlong(*ar, AR_mail_options); lSetUlong(*ar, AR_mail_options, ul | old_mail_opts); } lRemoveElem(pcmdline, &ep); } /* -M user[@host],... notify these e-mail addresses SGE_LIST*/ parse_list_simple(pcmdline, "-M", *ar, AR_mail_list, MR_host, MR_user, FLG_LIST_MERGE); /* -he yes/no hard error handling SGE_ULONG */ while ((ep = lGetElemStr(pcmdline, SPA_switch, "-he"))) { lSetUlong(*ar, AR_error_handling, lGetUlong(ep, SPA_argval_lUlongT)); lRemoveElem(pcmdline, &ep); } /* -now reserve in queues with qtype interactive SGE_ULONG */ while ((ep = lGetElemStr(pcmdline, SPA_switch, "-now"))) { u_long32 ar_now = lGetUlong(*ar, AR_type); if(lGetInt(ep, SPA_argval_lIntT)) { JOB_TYPE_SET_IMMEDIATE(ar_now); } else { JOB_TYPE_CLEAR_IMMEDIATE(ar_now); } lSetUlong(*ar, AR_type, ar_now); lRemoveElem(pcmdline, &ep); } /* Remove the script elements. They are not stored in the ar structure */ if ((ep = lGetElemStr(pcmdline, SPA_switch, STR_PSEUDO_SCRIPT))) { lRemoveElem(pcmdline, &ep); } if ((ep = lGetElemStr(pcmdline, SPA_switch, STR_PSEUDO_SCRIPTLEN))) { lRemoveElem(pcmdline, &ep); } if ((ep = lGetElemStr(pcmdline, SPA_switch, STR_PSEUDO_SCRIPTPTR))) { lRemoveElem(pcmdline, &ep); } ep = lFirst(pcmdline); if(ep) { const char *option = lGetString(ep,SPA_switch); /* as jobarg are stored no switch values, need to be filtered */ if(sge_strnullcmp(option, "jobarg") != 0) { answer_list_add_sprintf(alpp, STATUS_ESEMANTIC, ANSWER_QUALITY_ERROR, MSG_PARSE_INVALIDOPTIONARGUMENTX_S, lGetString(ep,SPA_switch)); } else { answer_list_add_sprintf(alpp, STATUS_ESEMANTIC, ANSWER_QUALITY_ERROR, MSG_PARSE_INVALIDOPTIONARGUMENT); } DRETURN(false); } if (lGetUlong(*ar, AR_start_time) == 0 && lGetUlong(*ar, AR_end_time) != 0 && lGetUlong(*ar, AR_duration) != 0) { lSetUlong(*ar, AR_start_time, lGetUlong(*ar, AR_end_time) - lGetUlong(*ar, AR_duration)); } else if (lGetUlong(*ar, AR_start_time) != 0 && lGetUlong(*ar, AR_end_time) == 0 && lGetUlong(*ar, AR_duration) != 0) { lSetUlong(*ar, AR_end_time, duration_add_offset(lGetUlong(*ar, AR_start_time), lGetUlong(*ar, AR_duration))); lSetUlong(*ar, AR_duration, lGetUlong(*ar, AR_end_time) - lGetUlong(*ar, AR_start_time)); } else if (lGetUlong(*ar, AR_start_time) != 0 && lGetUlong(*ar, AR_end_time) != 0 && lGetUlong(*ar, AR_duration) == 0) { lSetUlong(*ar, AR_duration, lGetUlong(*ar, AR_end_time) - lGetUlong(*ar, AR_start_time)); } DRETURN(true); }
static const char* sge_dstring_vsprintf_copy_append(dstring *sb, sge_dstring_copy_append_f function, const char *format, va_list ap) { const char *ret = NULL; if (sb != NULL && format != NULL && function != NULL) { char static_buffer[BUFSIZ]; int vsnprintf_ret; va_list ap_copy; va_copy(ap_copy, ap); vsnprintf_ret = vsnprintf(static_buffer, BUFSIZ, format, ap_copy); va_end(ap_copy); /* * We have to handle three cases here: * 1) If the function returns -1 then vsprintf does not follow * the C99 standard. We have to increase the buffer until * all parameters fit into the buffer. * 2) The function returns a value >BUFSIZE. This indicates * that the function follows the C99 standard. * vsnprintf_ret is the number of characters which would * have been written to the buffer if it where large enough. * We have to create a buffer of this size. * 3) If the return value is >0 and <BUFSIZ than vsprintf * was successfull. We do not need a dyn_buffer. */ if (vsnprintf_ret == -1) { size_t dyn_size = 2 * BUFSIZ; char *dyn_buffer = sge_malloc(dyn_size); while (vsnprintf_ret == -1 && dyn_buffer != NULL) { va_copy(ap_copy, ap); vsnprintf_ret = vsnprintf(dyn_buffer, dyn_size, format, ap_copy); va_end(ap_copy); if (vsnprintf_ret == -1) { dyn_size *= 2; dyn_buffer = sge_realloc(dyn_buffer, dyn_size, 0); } } if (dyn_buffer != NULL) { ret = function(sb, dyn_buffer); sge_free(&dyn_buffer); } else { /* error: no memory */ ret = NULL; } } else if (vsnprintf_ret > BUFSIZ) { char *dyn_buffer = NULL; dyn_buffer = (char *)malloc((vsnprintf_ret + 1) * sizeof(char)); if (dyn_buffer != NULL) { va_copy(ap_copy, ap); vsnprintf(dyn_buffer, vsnprintf_ret + 1, format, ap_copy); va_end(ap_copy); ret = function(sb, dyn_buffer); sge_free(&dyn_buffer); } else { /* error: no memory */ ret = NULL; } } else { ret = function(sb, static_buffer); } } return ret; }