/****** 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
}
예제 #3
0
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;
}   
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
/****** 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;
}
예제 #7
0
/****** 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;
}
예제 #8
0
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;

}
예제 #9
0
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;
}
예제 #10
0
파일: sge_env.c 프로젝트: HPCKP/gridengine
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;
}   
예제 #11
0
/****** 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;
}
예제 #12
0
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;
}
예제 #13
0
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;
}
예제 #14
0
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;
}
예제 #15
0
/****** 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() */
예제 #16
0
/****** 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);
}
예제 #17
0
파일: sge_log.c 프로젝트: HPCKP/gridengine
/****** 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() */
예제 #18
0
/****** 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);
}
예제 #19
0
파일: sge_log.c 프로젝트: HPCKP/gridengine
/****** 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() */
예제 #20
0
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);
      }
   }
예제 #22
0
/* 
 * 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;
}
예제 #23
0
/****** 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);
}
예제 #24
0
/****** 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; 
}
예제 #25
0
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);
}
예제 #26
0
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;
}