Ejemplo n.º 1
0
/* starts a new thread in detached state, which in turn calls start_new_process_wait() */
void process_manager_start_new_process_detached(int num, const char *projname, int do_exchange_processes)
{
    debug(1, "start new %d process%s for project %s, exchange=%d", num, (num>1?"es":""), projname, do_exchange_processes);
    /* Start the process creation thread in detached state because
     * we do not want to wait for it. Different from the handling
     * during the program startup there is no join() waiting for
     * the end of the thread and collecting its resources.
     */

    /* NOTE: aside from the general rule
     * "malloc() and free() within the same function"
     * we transfer the responsibility for this memory
     * to the thread itself.
     */
    struct thread_start_process_detached_args *targs = malloc(sizeof(*targs));
    assert(targs);
    if ( !targs )
    {
	logerror("ERROR: could not allocate memory");
	qexit(EXIT_FAILURE);
    }
    targs->num = num;
    targs->project_name = strdup(projname);
    targs->do_exchange_processes = do_exchange_processes;

    pthread_t thread;
    int retval = pthread_create(&thread, NULL, process_manager_thread_start_process_detached, targs);
    if (retval)
    {
	errno = retval;
	logerror("ERROR: pthread_create");
	qexit(EXIT_FAILURE);
    }

}
Ejemplo n.º 2
0
static void db_statement_finalize(sqlite3_stmt *ppstmt)
{
    int retval = sqlite3_finalize(ppstmt);
    if (SQLITE_OK != retval)
    {
	printlog("ERROR: finalizing sql statement: %s", sqlite3_errstr(retval));
	qexit(EXIT_FAILURE);
    }
}
Ejemplo n.º 3
0
static void db_global_unlock(void)
{
    int retval = pthread_mutex_unlock(&db_mutex_lock);
    if (retval)
    {
	errno = retval;
	logerror("ERROR: unlock db mutex lock");
	qexit(EXIT_FAILURE);
    }
}
Ejemplo n.º 4
0
//-----------------------------------------------------------------------
local void fatal(const char *format,...) {
  if ( infile[0] != '\0' && modname[0] != '\0' )
    fprintf(stderr,"Fatal [%s] (%s): ",infile,modname);
  va_list va;
  va_start(va,format);
  vfprintf(stderr,format,va);
  va_end(va);
  fprintf(stderr,"\n");
  fclose(outfp);
  unlink(outfile);
//  fprintf(stderr,"press enter to exit.\n");
//  getchar();
  qexit(1);
}
Ejemplo n.º 5
0
/* a child process died.
 * this may happen because we cancelled its operation or
 * the process died because of a bug or low memory or something else.
 * Get the project this process was tasked for. If there is no project then the
 * process was already scheduled to shut down or the process id did not belong
 * to us. Either way in this case we don't need to take action.
 * Else look for the number of idle processes and restart a new process if
 * needed.
 *
 * This function is called from the signal handler.
 * If the signal handler receives a SIGCHLD there may be more than one child
 * process having send a signal. We have to test all programs if they still
 * exist in RAM.
 */
void process_manager_process_died(void)
{
    int retval;
    pid_t *pidlist;
    int listlen;
    int i;

    retval = db_get_complete_list_process(&pidlist, &listlen);
    for(i=0; i<listlen; i++)
    {
	/* check if we are during shutdown sequence. if not then restart the
	 * process.
	 * check if the process died during the initialisation sequence
	 * if it did, remark the process being instable.
	 * then start a new one.
	 * Refrain from restarting if too much processes have died during the
	 * initialization.
	 */
	const pid_t pid = pidlist[i];

	retval = kill(pid, 0);
	if (-1 == retval)
	{
	    if (ESRCH == errno)
	    {
		/* child process died.
		 */
		process_manager_restart_process(pid);
	    }
	    else
	    {
		logerror("ERROR: kill(%d,0) returned", pid);
		qexit(EXIT_FAILURE);
	    }
	}
	else
	{
	    // process still exists, do not act on it
	}
    }

    db_free_list_process(pidlist, listlen);
}
Ejemplo n.º 6
0
static void *process_manager_thread_start_process_detached(void *arg)
{
    assert(arg);
    struct thread_start_process_detached_args *tinfo = arg;
    pthread_t thread_id = pthread_self();

    /* detach myself from the main thread. Doing this to collect resources after
     * this thread ends. Because there is no join() waiting for this thread.
     */
    int retval = pthread_detach(thread_id);
    if (retval)
    {
	errno = retval;
	logerror("ERROR: detaching thread");
	qexit(EXIT_FAILURE);
    }

    process_manager_start_new_process_wait(tinfo->num, tinfo->project_name, tinfo->do_exchange_processes);

    free(tinfo->project_name);
    free(arg);

    return NULL;
}
Ejemplo n.º 7
0
Archivo: map.cpp Proyecto: nealey/vera
//----------------------------------------------------------------------
uchar loadDialog(bool manual)
{
  static const char fmt[] =
"HELP\n"
"Java-VM class file loading options Ü\n"
" ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß\n"
"\n"
"Do not create 'import' segment with external-references\n"
"\n"
"  Prohibits the creation of a segment with external names, classes, and\n"
"  methods.\n"
"\n"
"\n"
"Create 'import' segment with with references from commands\n"
"\n"
"  Only regular references to the import segment will be collected.\n"
"  If this option is off, then all references (including simple text\n"
"  references) will be collected.\n"
"\n"
"\n"
"Field/variable declarations are included in references\n"
"\n"
"  Cross references from field declarations are collected in the import\n"
"  segment. For example, a field declaration\n"
"\n"
"    Field borland.ui.AboutDialog about\n"
"\n"
"  creates a reference to class borland.ui.AboutDialog\n"
"\n"
"\n"
"Method return types are included in references\n"
"\n"
"  Cross references from the return type and arguments of method\n"
"  declarations are collected in the import segment.\n"
"  NOTE: The import segment does not contain classes that appear only in\n"
"        the arguments of the method declarations.\n"
"\n"
"Store unknown attributes to external files\n"
"\n"
"  This option allows to extract non-standard attributes (if present)\n"
"  and store them to a set of files in the current directory.\n"
"  Filenames will have <classname>.<tagname>.<attributename> form\n"
"\n"
"\n"
"Rename local (slot) variables (if information is available)\n"
"\n"
"  This option allows to use names from variable declarations to\n"
"  rename local variables if the input file has this information.\n"
"\n"
"\n"
"Create visible representation of stripped names\n"
"\n"
"  Some java classes have their local\n"
"  names stripped. This option allows IDA to recreate such local names.\n"
"  NOTE: If this option is selected then all one-character names with\n"
"        the character code >= 0x80 will be ignored.\n"
"\n"
"\n"
"Continue loading after errors in additional attributes\n"
"\n"
"  Normally all errors in the classfile structure are fatal.\n"
"  If this option is on, errors in the additional attributes\n"
"  produce only warnings and the loading process continues.\n"
"\n"
"ENDHELP\n"
"Java loading options\n"
"\n"
"            Class File version %D.%D (JDK1.%D%A)\n"
"\n"
"\n"
"<~D~o not create 'import' segment with external-references :R>\n"
"<~C~reate 'import' segment with references from commands   :R>\n"
"<~F~ield/variable declarations are included in references  :R>\n"
"<~M~ethod return types are included in references          :R>>\n"
"\n"
"<~S~tore unknown attributes to external files              :C>\n"
"<~R~ename local (slot) variables (if info is available)    :C>\n"
"<Create ~v~isible representation of stripped names         :C>\n"
"<Continue ~l~oading after errors in additional attributes  :C>>\n"
"\n"
"\n";

#if ((MLD__DEFAULT & MLD_METHREF) && !(MLD__DEFAULT & MLD_VARREF)) || \
    ((MLD__DEFAULT & MLD_VARREF)  && !(MLD__DEFAULT & MLD_EXTREF))
#error
#endif

  if(!manual) return(MLD__DEFAULT);

  short rtyp =
#if   (MLD__DEFAULT & MLD_METHREF)
                3,
#elif (MLD__DEFAULT & MLD_VARREF)
                2,
#elif (MLD__DEFAULT & MLD_EXTREF)
                1,
#else
                0,
#endif
        mod   = (MLD__DEFAULT & (MLD_EXTATR | MLD_LOCVAR | MLD_STRIP |
                                 MLD_FORCE)) >> 3;
#if (MLD_EXTATR >> 3) != 1 || (MLD_LOCVAR >> 3) != 2 || \
    (MLD_STRIP >> 3) != 4 || (MLD_FORCE >> 3) != 8
#error
#endif
  {
    uval_t maxv = curClass.MajVers,
           minv = curClass.MinVers,
           jdk  = curClass.JDKsubver;

    if(!AskUsingForm_c(fmt, &maxv, &minv, &jdk,
                       jdk == 3 ? "/CLDC" : "",
                       &rtyp, &mod)) qexit(1);
  }

  idpflags &= ~IDM_REQUNK;  // do not use 'request mode' when 'manual options'

  uchar ans = 0;

#if MLD_EXTATR != (1<<3) || MLD_LOCVAR != (2<<3) || MLD_STRIP != (4<<3) || \
    MLD_FORCE != (8<<3)
#error
#endif
  ans |= ((uchar)mod) << 3;
#if MLD_EXTREF != 1 || MLD_VARREF != 2 || MLD_METHREF  != 4
#error
#endif
  ans |= (uchar)((1 << rtyp) - 1);
  return(ans);
}
Ejemplo n.º 8
0
/* starts "num" new child processes synchronously.
 * param num: number of processes to start (num>=0)
 * param project: project to manage them
 * param do_exchange_processes: if true removes all active processes and replaces them with the new created ones.
 *                              else integrate them in the list of active processes.
 */
void process_manager_start_new_process_wait(int num, const char *projname, int do_exchange_processes)
{
    assert(projname);
    assert(num > 0);

    pthread_t threads[num];
    int i;
    int retval;




    retval = db_get_startup_failures(projname);
    if ( 0 > retval )
    {	// too much dying processes during init phase, do not start new processes
	printlog("ERROR: can not get number of startup failures, function call failed for project %s", projname);
	qexit(EXIT_FAILURE);
    }
    else if (max_nr_process_crashes > retval+1)
    {


	printlog("Starting %d process%s for project '%s'", num, (num>1)?"es":"", projname);

	/* start all thread in parallel */
	for (i=0; i<num; i++)
	{
	    /* NOTE: aside from the general rule
	     * "malloc() and free() within the same function"
	     * we transfer the responsibility for this memory
	     * to the thread itself.
	     */
	    struct thread_start_new_child_args *targs = malloc(sizeof(*targs));
	    assert(targs);
	    if ( !targs )
	    {
		logerror("ERROR: could not allocate memory");
		qexit(EXIT_FAILURE);
	    }
	    targs->project_name = strdup(projname);

	    retval = pthread_create(&threads[i], NULL, process_manager_thread_start_new_child, targs);
	    if (retval)
	    {
		errno = retval;
		logerror("ERROR: creating thread");
		qexit(EXIT_FAILURE);
	    }
	    debug(1, "[%lu] started thread %lu", pthread_self(), threads[i]);
	}
	/* wait for those threads */
	for (i=0; i<num; i++)
	{
	    debug(1, "[%lu] join thread %lu", pthread_self(), threads[i]);
	    retval = pthread_join(threads[i], NULL);
	    if (retval)
	    {
		errno = retval;
		logerror("ERROR: joining thread");
		qexit(EXIT_FAILURE);
	    }
	}


	/* move the processes from the initialization list to the active process
	 * list.
	 * If we got the option to exchange the processes then first move all
	 * existing processes from the active list to the shutdown queue.
	 *
	 * Note: The option to exchange the processes is usually set if a new
	 * configuration file has been copied to the processes.
	 * If a new configuration file arrives the number of crashed processes is
	 * reset. But if we do this during a crashing process, the number becomes
	 * invalid. So we can not reset the number in
	 * qgis_project_check_inotify_config_changed(), because it is not
	 * protected. We have the reset the number over here.
	 */
	if (do_exchange_processes)
	{
	    // TODO: move only those processes which have been started above
	    db_move_all_process_from_active_to_shutdown_list(projname);
	    db_reset_startup_failures(projname);	// TODO: move this line to the config change manager
	}

	db_move_all_idle_process_from_init_to_active_list(projname);

	statistic_add_process_start(num);

    }
    else
    {
	printlog("WARNING: max number (%d) of startup failures in project %s reached."
		" Stoppped creating new processes until the configuration for this project has changed",
		max_nr_process_crashes, projname);
    }

}
Ejemplo n.º 9
0
/* return the child process id if successful, 0 otherwise */
static int process_manager_thread_function_start_new_child(struct thread_start_new_child_args *tinfo)
{
    assert(tinfo);
    const char *project_name = tinfo->project_name;
    const char *command = config_get_process( project_name );

    debug(1, "project '%s' start new child process '%s'", project_name, command);

    if (NULL == command || 0 == strlen(command))
    {
	printlog("ERROR: no process path specified. Not starting any process for project '%s'", project_name);
	return 0;
    }

    /* prepare the socket to connect to this child process only */
    /* NOTE: Linux allows abstract socket names which have no representation
     * in the filesystem namespace.
     */
    int retval = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
    if (-1 == retval)
    {
	logerror("ERROR: can not create socket for fcgi program");
	qexit(EXIT_FAILURE);
    }
    const int childsocket = retval;


    /* Create a unique socket name without a file system inode.
     * The name is "\0qgis-schedulerd-socket0", "..1", etc.
     * We just count upwards until integer overflow and then start
     * over at 0.
     * If one name is already given to a socket, bind() returns EADDRINUSE.
     * In this case we try again.
     */

    /* security rope for the really unlikely case
     * that we got no more numbers free.
     * To prevent infinite loop
     */
    retval = pthread_mutex_lock (&socket_id_mutex);
    if (retval)
    {
	errno = retval;
	logerror("ERROR: acquire mutex");
	qexit(EXIT_FAILURE);
    }
    unsigned int socket_suffix_start = socket_id-1;
    retval = pthread_mutex_unlock (&socket_id_mutex);
    if (retval)
    {
	errno = retval;
	logerror("ERROR: unlock mutex");
	qexit(EXIT_FAILURE);
    }

    for (;;)
    {
	retval = pthread_mutex_lock (&socket_id_mutex);
	if (retval)
	{
	    errno = retval;
	    logerror("ERROR: acquire mutex");
	    qexit(EXIT_FAILURE);
	}
	unsigned int socket_suffix = socket_id++;
	retval = pthread_mutex_unlock (&socket_id_mutex);
	if (retval)
	{
	    errno = retval;
	    logerror("ERROR: unlock mutex");
	    qexit(EXIT_FAILURE);
	}

	if (socket_suffix == socket_suffix_start)
	{
	    /* we tested UINT_MAX numbers without success.
	     * exit here, because we can not get any more numbers.
	     * Or we have a programmers error here..
	     */
	    debug(1, "ERROR: out of numbers to create socket name. exit");
	    qexit(EXIT_FAILURE);
	}

	struct sockaddr_un childsockaddr;
	childsockaddr.sun_family = AF_UNIX;
	retval = snprintf( childsockaddr.sun_path, sizeof(childsockaddr.sun_path), "%c%s%u", '\0', base_socket_desc, socket_suffix );
	if (-1 == retval)
	{
	    logerror("ERROR: calling string format function snprintf");
	    qexit(EXIT_FAILURE);
	}

	retval = bind(childsocket, (struct sockaddr *)&childsockaddr, sizeof(childsockaddr));
	if (-1 == retval)
	{
	    if (EADDRINUSE==errno)
	    {
		continue;	// reiterate with next number
	    }
	    else
	    {
		logerror("ERROR: calling bind");
		qexit(EXIT_FAILURE);
	    }
	}
	debug(1, "start project '%s', bound socket to '\\0%s'", project_name, childsockaddr.sun_path+1);
	break;
    }

    /* the child process listens for connections, one at a time */
    retval = listen(childsocket, 1);
    if (-1 == retval)
    {
	logerror("ERROR: can not listen to socket connecting fast cgi application");
	qexit(EXIT_FAILURE);
    }


    /* preparation of data before fork() so we don't need to call functions with
     * mutexes after fork() (see below for further reading).
     */
    static const int maxenv = 128;	// to prevent infinite loop support 128 environment variables at max
    int lenkey = 0;
    int numkey = 0;
    const char **keys = NULL;
    const char **values = NULL;
    int i;
    for (i=0; i<maxenv; i++)
    {
	const char *key = config_get_env_key(project_name, i);
	if ( !key )
	    break;
	const char *value = config_get_env_value(project_name, i);
	if ( !value )
	    break;

	int lenvalue = lenkey;
	int numvalue = numkey;
	arraycat(&values, &numvalue, &lenvalue, &value, sizeof(*values) );
	arraycat(&keys, &numkey, &lenkey, &key, sizeof(*keys) );
	debug(1, "project %s: add %s = %s to environment", project_name, key, value);
    }

    const char *working_directory = config_get_working_directory(project_name);


    pid_t pid = fork();
    if (0 == pid)
    {
	/* child */

	/* according to
	 * http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them
	 * we may only call async-safe functions in multithreaded programs (this!)
	 * after calling fork() (here!).
	 *
	 * So we are not allowed to call ANY function with in turn calls locks
	 * or mutexes. We should only call functions which are listed as async-safe
	 * in signal(7).
	 * NOTE: setenv() is not listed as async-safe. Unfortunately I don't see
	 * any other safe way to prepare the environment for the child only?
	 * Maybe kill all threads (except this) with a combination of
	 * pthread_atfork() and pthread_cancel() ?
	 */

	/* Add the configured environment to the existing environment */
	/* Note: shall we clean up before? */
	for (i=0; i<lenkey; i++)
	{
//	    debug(1, "project %s: add %s = %s to environment", project_name, key, value); # no debug message allowed because of locking
	    retval = setenv(keys[i], values[i], 1);
	    if (retval)
	    {
//		logerror("ERROR: can not set environment with key='%s' and value='%s'", key[i], value[i]); # no log message allowed because of locking
		qexit(EXIT_FAILURE);
	    }
	}
	// no need to free() memory, is freed by exec()

	/* change working dir
	 * close file descriptor stdin = 0
	 * assign socket file descriptor to fd 0
	 * fork
	 * exec
	 */
	retval = chdir(working_directory);
	if (-1 == retval)
	{
//	    logerror("ERROR: calling chdir"); # no log message allowed because of locking
	}


	retval = dup2(childsocket, FCGI_LISTENSOCK_FILENO);
	if (-1 == retval)
	{
//	    logerror("ERROR: calling dup2"); # no log message allowed because of locking
	    qexit(EXIT_FAILURE);
	}


	/* close all file descriptors different from 0. The fd different from
	 * 1 and 2 are opened during open() and socket() calls with FD_CLOEXEC
	 * flag enabled. This way, all fds are closed during exec() call.
	 * TODO: assign an error log file to fd 1 and 2
	 */
	close(STDOUT_FILENO);
	close(STDERR_FILENO);


	execl(command, command, NULL);
//	logerror("ERROR: could not execute '%s': ", command); # no log message allowed because of locking
	qexit(EXIT_FAILURE);
    }
    else if (0 < pid)
    {
	/* parent */
	free(keys);
	free(values);
	debug(1, "project '%s' started new child process '%s', pid %d", project_name, command, pid);
	db_add_process( project_name, pid, childsocket);

	return pid;
    }
    else
    {
	/* error */
	logerror("ERROR: can not fork");
	qexit(EXIT_FAILURE);
    }

    return 0;
}
Ejemplo n.º 10
0
static void process_manager_thread_function_init_new_child(struct thread_init_new_child_args *tinfo)
{
    assert(tinfo);
    const pid_t pid = tinfo->pid;
    assert(pid > 0);
    const char *projname = tinfo->project_name;
    assert(projname);
    const pthread_t thread_id = pthread_self();
    char *buffer = NULL;
    int retval;
    int has_child_crash = 0;
    int len;
    struct fcgi_message_s *message = NULL;

    db_process_set_state_init(pid, thread_id);


    debug(1, "init new spawned child process for project '%s'", projname);


//    char debugfile[256];
//    sprintf(debugfile, "/tmp/threadinit.%lu.dump", thread_id);
//    int debugfd = open(debugfile, (O_WRONLY|O_CREAT|O_TRUNC), (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH));
//    if (-1 == debugfd)
//    {
//	debug(1, "ERROR: can not open file '%s': ", debugfile);
//	logerror(NULL);
//	qexit(EXIT_FAILURE);
//    }


    /* open the socket to the child process */

    struct sockaddr_un sockaddr;
    socklen_t sockaddrlen = sizeof(sockaddr);
    int childunixsocketfd = db_get_process_socket(pid);

    retval = getsockname(childunixsocketfd, (struct sockaddr *)&sockaddr, &sockaddrlen);
    if (-1 == retval)
    {
	logerror("ERROR: retrieving the name of child process socket %d", childunixsocketfd);
	has_child_crash = 1;
    }
    /* leave the original child socket and create a new one on the opposite
     * side.
     * create the socket in blocking mode (non SOCK_NONBLOCK) because we need the
     * read() and write() calls waiting on it.
     */
    if (!has_child_crash)
    {
	retval = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
	if (-1 == retval)
	{
	    logerror("ERROR: can not create socket to child process");
	    has_child_crash = 1;
	}
    }
    if (!has_child_crash)
    {
	childunixsocketfd = retval;	// refers to the socket this program connects to the child process
	retval = connect(childunixsocketfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
	if (-1 == retval)
	{
	    logerror("ERROR: init can not connect to child process");
	    has_child_crash = 1;
	}
    }
//    debug(1, "init project '%s', connected to child via socket '\\0%s'", projname, sockaddr.sun_path+1);


    static const int maxbufferlen = 4096;
    static const int requestid = 1;
    if (!has_child_crash)
    {
	/* create the fcgi data and
	 * send the fcgi data to the child process
	 */
	buffer = malloc(maxbufferlen);
	assert(buffer);
	if ( !buffer )
	{
	    logerror("ERROR: could not allocate memory");
	    qexit(EXIT_FAILURE);
	}

	message = fcgi_message_new_begin(requestid, FCGI_RESPONDER, 0);
	len = fcgi_message_write(buffer, maxbufferlen, message);
	if (-1 == len)	// TODO: be more flexible if buffer too small
	{
	    debug(1, "fcgi message buffer too small (%d)", maxbufferlen);
	    qexit(EXIT_FAILURE);
	}
//	retval = write(debugfd, buffer, len);
	retval = write(childunixsocketfd, buffer, len);
	if (-1 == retval)
	{
	    logerror("ERROR: can not write to child process");
	    has_child_crash = 1;
	}
	//printf(stderr, "write to child prog (%d): %.*s\n", retval, buffer, retval);
	fcgi_message_delete(message);
    }

    if (!has_child_crash)
    {
	char *parambuffer = (char *)buffer;
	int remain_len = maxbufferlen;

	int i;
	for (i=0; i<128; i++)
	{
	    const char *key = config_get_init_key(projname, i);
	    if (!key)
		break;
	    const char *value = config_get_init_value(projname, i);
	    if (!value)
		break;
	    debug(1, "Param %s=%s", key, value);

	    retval = fcgi_param_list_write(parambuffer, remain_len, key, value);
	    if (-1 == retval)
	    {
		// TODO: be more flexible if buffer too small
		debug(1, "fcgi parameter buffer too small (%d)", maxbufferlen);
		qexit(EXIT_FAILURE);

	    }

	    parambuffer += retval;
	    remain_len -= retval;

	}
	len = maxbufferlen - remain_len;

	if (i>=128)
	{
	    debug(1, "fcgi parameter too many key/value pairs");
	    has_child_crash = 1;
	}
    }

    if (!has_child_crash)
    {
	/* send parameter list */
	message = fcgi_message_new_parameter(requestid, buffer, len);
	len = fcgi_message_write(buffer, maxbufferlen, message);
	if (-1 == len)	// TODO: be more flexible if buffer too small
	{
	    debug(1, "fcgi message buffer too small (%d)", maxbufferlen);
	    qexit(EXIT_FAILURE);
	}
//	retval = write(debugfd, buffer, len);
	retval = write(childunixsocketfd, buffer, len);
	if (-1 == retval)
	{
	    logerror("ERROR: can not write to child process");
	    has_child_crash = 1;
	}
	fcgi_message_delete(message);
    }

    if (!has_child_crash)
    {
	/* send empty parameter list to signal EOP */
	message = fcgi_message_new_parameter(requestid, "", 0);
	len = fcgi_message_write(buffer, maxbufferlen, message);
	if (-1 == len)	// TODO: be more flexible if buffer too small
	{
	    debug(1, "fcgi message buffer too small (%d)", maxbufferlen);
	    qexit(EXIT_FAILURE);
	}
//	retval = write(debugfd, buffer, len);
	retval = write(childunixsocketfd, buffer, len);
	if (-1 == retval)
	{
	    logerror("ERROR: can not write to child process");
	    has_child_crash = 1;
	}
	fcgi_message_delete(message);
    }

    if (!has_child_crash)
    {
	message = fcgi_message_new_stdin(requestid, "", 0);
	len = fcgi_message_write(buffer, maxbufferlen, message);
	if (-1 == len)
	{
	    debug(1, "fcgi message buffer too small (%d)", maxbufferlen);
	    qexit(EXIT_FAILURE);
	}
//	retval = write(debugfd, buffer, len);
	retval = write(childunixsocketfd, buffer, len);
	if (-1 == retval)
	{
	    logerror("ERROR: can not write to child process");
	    has_child_crash = 1;
	}
	// write stdin = "" twice
	if (!has_child_crash)
	{
//	    retval = write(debugfd, buffer, len);
	    retval = write(childunixsocketfd, buffer, len);
	    if (-1 == retval)
	    {
		logerror("ERROR: can not write to child process");
		has_child_crash = 1;
	    }
	}
	fcgi_message_delete(message);
    }

    if (!has_child_crash)
    {
	/* now read from socket into void until no more data
	 * we do it to make sure that the child process has completed the request
	 * and filled up its cache.
	 *
	 * Set a timeout of N seconds in case the program crashed during start. If
	 * the timeout catches move the process to the shutdown module and in the
	 * database mark the process as crashed.
	 */
	const int init_read_timeout = config_get_read_timeout(projname);
	retval = 1;
	while (retval>0)
	{
	    retval = read_timeout(childunixsocketfd, buffer, maxbufferlen, init_read_timeout*1000);
//	    debug(1, "init project '%s' received:\n%.*s", projname, retval, buffer);
	    if (-1 == retval)
	    {
		logerror("ERROR: read() from child process during init phase");
		if (ETIMEDOUT == errno)
		{
		    has_child_crash = 1;
		}
	    }
	}
    }

    /* if the child process died during the initialization we need to figure
     * this out.
     * there may be a race condition between the signal handler and this thread
     * so we test the existence of the child process after the read.
     */
    if (has_child_crash)
    {
	printlog("starting new process for project %s", projname);
	process_manager_restart_process(pid);
	process_manager_process_died_during_init(pid, projname);
    }
    else
    {
	retval = kill(pid, 0);
	if (-1 == retval)
	{
	    if (ESRCH == errno)
	    {
		/* child process died during initialization.
		 * start a new one if possible
		 */
		process_manager_process_died_during_init(pid, projname);
	    }
	    else
	    {
		logerror("ERROR: kill(%d,0) returned", pid);
		qexit(EXIT_FAILURE);
	    }
	}
	else
	{
	    db_process_set_state_idle(pid);
	}
    }

    /* ok, we did read each and every byte from child process.
     * now close this and set idle
     * Try to close the file secriptor even if error occurred previously
     */
    retval = close(childunixsocketfd);
    debug(1, "closed child socket fd %d, retval %d, errno %d", childunixsocketfd, retval, errno);
//    close(debugfd);
    debug(1, "init child process for project '%s' done. waiting for input..", projname);


    free(buffer);
}
Ejemplo n.º 11
0
static int db_select_parameter_callback(enum db_select_statement_id sid, db_callback callback, void *callback_arg, ...)
{
    /* The life-cycle of a prepared statement object usually goes like this:
     *
     * 1. Create the prepared statement object using sqlite3_prepare_v2().
     * 2. Bind values to parameters using the sqlite3_bind_*() interfaces.
     * 3. Run the SQL by calling sqlite3_step() one or more times.
     * 4. Reset the prepared statement using sqlite3_reset() then go back to step 2. Do this zero or more times.
     * 5. Destroy the object using sqlite3_finalize().
     */
    int retval;
    const int loglevel = config_get_debuglevel();

#define BUFFERSIZE 64
    char debug_buffer[BUFFERSIZE] = {0,};
    int debug_loglen = BUFFERSIZE;
    char *debug_log = NULL;
    if (1 <= loglevel)
    {
	debug_log = malloc(BUFFERSIZE);
	if (NULL == debug_log)
	{
	    logerror("ERROR: malloc");
	    qexit(EXIT_FAILURE);
	}
	*debug_log = '\0';
    }

    assert(dbhandler);
    assert(sid < DB_SELECT_ID_MAX);
    const char *sql = db_select_statement[sid];

    sqlite3_stmt *ppstmt;
    if ( !db_prepared_stmt[sid] )
	db_prepared_stmt[sid] =
		ppstmt = db_statement_prepare(sid);
    else
	ppstmt = db_prepared_stmt[sid];

    /* evaluate the remaining arguments */
    int col = 1;	// column position index
    va_list args;
    va_start(args, callback_arg);
    while (*sql)
    {
	if ('%' == *sql++)
	{
	    switch(*sql++)
	    {
	    case 'p':
		/* found pointer value "%p". The next argument is the
		 * type "void *" */
	    {
		assert(0); // TODO need to extend "%p" to "%NNNp" with NNN being decimal number describing the size of 'p'
                const void *v = va_arg(args, void *);
                retval = sqlite3_bind_blob(ppstmt, col++, v, -1, SQLITE_STATIC);
                if ( SQLITE_OK != retval )
                {
                    printlog("ERROR: in sql '%s' bind column %d returned: %s", sql, col, sqlite3_errstr(retval));
                    qexit(EXIT_FAILURE);
                }
                if (1 <= loglevel)
                {
                    snprintf(debug_buffer, BUFFERSIZE-1, ", %p", v);
                    strnbcat(&debug_log, &debug_loglen, debug_buffer);
                }
		break;
	    }

	    case 'f':
		/* found double value "%f". The next argument is the
		 * type "double" */
	    {
                double d = va_arg(args, double);
                retval = sqlite3_bind_double(ppstmt, col++, d);
                if ( SQLITE_OK != retval )
                {
                    printlog("ERROR: in sql '%s' bind column %d returned: %s", sql, col, sqlite3_errstr(retval));
                    qexit(EXIT_FAILURE);
                }
                if (1 <= loglevel)
                {
                    snprintf(debug_buffer, BUFFERSIZE-1, ", %f", d);
                    strnbcat(&debug_log, &debug_loglen, debug_buffer);
                }
		break;
	    }

	    case 's':
		/* found string value "%s". The next argument is the
		 * type "const char *" */
	    {
                const char *s = va_arg(args, char *);
                retval = sqlite3_bind_text(ppstmt, col++, s, -1, SQLITE_STATIC);
                if ( SQLITE_OK != retval )
                {
                    printlog("ERROR: in sql '%s' bind column %d returned: %s", sql, col, sqlite3_errstr(retval));
                    qexit(EXIT_FAILURE);
                }
                if (1 <= loglevel)
                {
                    snprintf(debug_buffer, BUFFERSIZE-1, ", %s", s);
                    strnbcat(&debug_log, &debug_loglen, debug_buffer);
                }
		break;
	    }

	    case 'd':	// fall through
	    case 'i':
		/* found integer value "%i". The next argument is the
		 * type "int" */
	    {
                int i = va_arg(args, int);
                retval = sqlite3_bind_int(ppstmt, col++, i);
                if ( SQLITE_OK != retval )
                {
                    printlog("ERROR: in sql '%s' bind column %d returned: %s", sql, col, sqlite3_errstr(retval));
                    qexit(EXIT_FAILURE);
                }
                if (1 <= loglevel)
                {
                    snprintf(debug_buffer, BUFFERSIZE-1, ", %d", i);
                    strnbcat(&debug_log, &debug_loglen, debug_buffer);
                }
		break;
	    }

	    case 'l':
		/* found 64bit integer value "%l". The next argument is the
		 * type "long long int" */
	    {
                long long int l = va_arg(args, long long int);
                retval = sqlite3_bind_int64(ppstmt, col++, l);
                if ( SQLITE_OK != retval )
                {
                    printlog("ERROR: in sql '%s' bind column %d returned: %s", sql, col, sqlite3_errstr(retval));
                    qexit(EXIT_FAILURE);
                }
                if (1 <= loglevel)
                {
                    snprintf(debug_buffer, BUFFERSIZE-1, ", %lld", l);
                    strnbcat(&debug_log, &debug_loglen, debug_buffer);
                }
		break;
	    }

	    case '%':
		/* found double percent sign "%%". just go on */
		break;

	    case '\0':
		/* percentage sign has been the last character in the string
		 * rewind the string, so the outer while() catches the end of
		 * the string.
		 */
		sql--;
		break;

	    default:
		/* unknown character found. exit */
		printlog("ERROR: unknown character found in sql string '%s', position %ld: %c", db_select_statement[sid], (long int)(sql - db_select_statement[sid]), *sql);
		qexit(EXIT_FAILURE);
	    }
	}
    }
    va_end(args);
    debug(1, "db selected %d: '%s%s'", sid, db_select_statement[sid], debug_log);
    free(debug_log);

    int try_num = 0;
    do {
	retval = sqlite3_step(ppstmt);
	if (SQLITE_BUSY == retval)
	    try_num++;
	else if (SQLITE_ROW == retval)
	{
	    /* there is data available, fetch data and recall step() */
	    debug(1, "data available: sql '%s'", db_select_statement[sid]);
	    assert(callback);
	    if ( !callback )
	    {
		printlog("ERROR: data available but no callback function defined for sql '%s'", db_select_statement[sid]);
		/* go on with the loop until no more data is available */
	    }
	    else
	    {
		/* prepare the callback data */
		const int ncol_result = sqlite3_column_count(ppstmt);
		int *type = calloc(ncol_result, sizeof(*type));
		if ( !type )
		{
		    printlog("ERROR: not enough memory");
		    qexit(EXIT_FAILURE);
		}
		union callback_result_t *results = calloc(ncol_result, sizeof(*results));
		if ( !results )
		{
		    printlog("ERROR: not enough memory");
		    qexit(EXIT_FAILURE);
		}
		const char **cols = calloc(ncol_result, sizeof(*cols));
		if ( !cols )
		{
		    printlog("ERROR: not enough memory");
		    qexit(EXIT_FAILURE);
		}

		int i;
		for (i = 0; i<ncol_result; i++)
		{
		    int mytype =
			    type[i] = sqlite3_column_type(ppstmt, i);
		    switch(mytype)
		    {
		    case SQLITE_INTEGER:
			results[i].integer = sqlite3_column_int64(ppstmt, i);
			break;

		    case SQLITE_FLOAT:
			results[i].floating = sqlite3_column_double(ppstmt, i);
			break;

		    case SQLITE_TEXT:
			results[i].text = sqlite3_column_text(ppstmt, i);
			break;

		    case SQLITE_BLOB:
			results[i].blob = sqlite3_column_blob(ppstmt, i);
			break;

		    case SQLITE_NULL:
			break;

		    default:
			printlog("ERROR: unknown type %d", mytype);
			qexit(EXIT_FAILURE);
		    }
		    cols[i] = sqlite3_column_name(ppstmt, i);
		}

		retval = callback(callback_arg, ncol_result, type, results, cols);

		//TODO: reuse arrays for the next row
		free(type);
		free(results);
		free(cols);

		if (retval)
		{
		    retval = SQLITE_ABORT;
		    break;
		}
	    }
	}
	else
	    break;
    } while (try_num < DB_MAX_RETRIES);

    switch(retval)
    {
    case SQLITE_BUSY:
	printlog("ERROR: db busy! Exceeded max calls (%d) to fetch data", try_num);
	break;

    case SQLITE_ROW:
	/* error: there has been data available,
	 * but the program broke out of the loop?
	 */
	assert(0);
	break;

    case SQLITE_ERROR:
	/* there has been a data error. Print out and reset() the statement */
    {
	const char *sql = db_select_statement[sid];
	printlog("ERROR: stepping sql statement '%s': %s", sql, sqlite3_errstr(retval));
	if (db_exit_on_error)
	{
	    printlog("exiting..");
	    qexit(EXIT_FAILURE);
	}
	else
	{
	    retval = sqlite3_reset(ppstmt);
	    if (SQLITE_OK != retval)
	    {
		printlog("ERROR: resetting sql statement '%s': %s", sql, sqlite3_errstr(retval));
	    }
	}
    }
    break;

    case SQLITE_MISUSE:
	/* the statement has been incorrect */
	printlog("ERROR: misuse of prepared sql statement '%s'", db_select_statement[sid]);
	if (db_exit_on_error)
	{
	    printlog("exiting..");
	    qexit(EXIT_FAILURE);
	}
	break;

    case SQLITE_ABORT:
	printlog("ERROR: abort in callback function during steps of sql '%s'", db_select_statement[sid]);
	qexit(EXIT_FAILURE);
	break;

    case SQLITE_OK:
    case SQLITE_DONE:
	/* the statement has finished successfully */
	retval = sqlite3_reset(ppstmt);
	if (SQLITE_OK != retval)
	{
	    const char *sql = db_select_statement[sid];
	    printlog("ERROR: resetting sql statement '%s': %s", sql, sqlite3_errstr(retval));
	    qexit(EXIT_FAILURE);
	}
	break;
    }

//    if ( !db_prepared_stmt[sid] )
//	db_statement_finalize(ppstmt);

    return 0;
}
Ejemplo n.º 12
0
static sqlite3_stmt *db_statement_prepare(enum db_select_statement_id sid)
{
    assert(sid < DB_SELECT_ID_MAX);

    sqlite3_stmt *ppstmt;
    const char *const sql = db_select_statement[sid];
    const char *srcsql = sql;

    /* exchange "%N" markers with '?' */
    char * const copysql = strdup(sql);
    char *destsql = copysql;
    char c;
    do
    {
	c = *srcsql++;
	if ('%' == c)
	{
	    switch(*srcsql++)
	    {
	    case 'p':
		/* found pointer value "%p". */
		// fall through
	    case 'f':
		/* found double value "%f". */
		// fall through
	    case 's':
		/* found string value "%s". */
		// fall through
	    case 'd':
		/* found integer value "%i". */
		// fall through
	    case 'i':
		/* found integer value "%i". */
		// fall through
	    case 'l':
		/* found long long integer value "%l". */

		/* exchange "%N" with '?' */
		c = '?';
		break;

	    case '%':
		/* found double percent sign "%%". just go on */

		/* exchange "%%" with '%' */
		break;

	    case '\0':
		/* percentage sign has been the last character in the string
		 * rewind the string, so the outer while() catches the end of
		 * the string.
		 */
		debug(1, "Huh? found '%%' at the end of the sql '%s'", sql);
		srcsql--;
		break;

	    default:
		/* unknown character found. exit */
		srcsql--;
		printlog("ERROR: unknown character found in sql string '%s', position %ld: '%c'", db_select_statement[sid], (long int)(srcsql - db_select_statement[sid]), *srcsql);
		qexit(EXIT_FAILURE);
	    }
	}

	*destsql++ = c;
    } while ( c ); // moved while() down here to copy terminating '\0' to "destsql"
    debug(1, "transferred sql from '%s' to '%s'", sql, copysql);

    int retval = sqlite3_prepare(dbhandler, copysql, -1, &ppstmt, NULL);
    if (SQLITE_OK != retval)
    {
	printlog("ERROR: preparing sql statement '%s': %s", sql, sqlite3_errstr(retval));
	qexit(EXIT_FAILURE);
    }

    free(copysql);

    return ppstmt;
}
Ejemplo n.º 13
0
//----------------------------------------------------------------------
int upgrade_db_format(int ver, netnode constnode)
{
  if(askyn_c(1, "AUTOHIDE REGISTRY\nHIDECANCEL\n"
                "The database has an old java data format.\n"
                "Do you want to upgrade it?") <= 0) qexit(1);

  switch ( ver ) {
    default:
      INTERNAL("upgrade::ver");
    case IDP_JDK12:
      break;
  }

  // change format: jdk-version
  if ( curClass.MinVers > 0x8000u ) {
badbase:
    return(0);
  }

  curClass.MajVers = JDK_MIN_MAJOR;
  if ( curClass.MinVers >= 0x8000 ) {
    curClass.MinVers &= ~0;
    ++curClass.MajVers;
    curClass.JDKsubver = 2;
  } else if ( curClass.MinVers >= JDK_1_1_MINOR ) ++curClass.JDKsubver;

// change format: This
#ifdef __BORLANDC__
#if offsetof(ClassInfo, This.Ref)  != offsetof(ClassInfo, This.Name) || \
    offsetof(ClassInfo, This.Dscr) != offsetof(ClassInfo, This.Name) + 2
#error
#endif
#endif
   curClass.This.Ref = (curClass.This.Ref << 16) | curClass.This.Dscr;
   if ( !curClass.This.Name ) goto badbase;

// change format: Super
#ifdef __BORLANDC__
#if offsetof(ClassInfo, super.Ref)  != offsetof(ClassInfo, super.Name) || \
    offsetof(ClassInfo, super.Dscr) != offsetof(ClassInfo, super.Name) + 2
#error
#endif
#endif
  switch ( curClass.super.Name ) {
    case 0:       // absent
      curClass.super.Ref &= 0;
      break;
    case 0xFFFF:  // bad index
      ++curClass.super.Name;
      break;
    default:      // reverse order
      curClass.super.Ref = (curClass.super.Ref << 16) | curClass.super.Dscr;
      break;
  }

// validate: impNode
  if ( curClass.impNode && !netnode(curClass.impNode).altval(0) ) goto badbase;

// change variable 'errload' in previous version
  if ( curClass.maxSMsize ) {
    curClass.extflg |= XFL_C_ERRLOAD;
    curClass.maxSMsize &= 0;
  }

// set segments type type for special segments
  segment_t *S;
  if ( (S = getseg(curClass.startEA)) == NULL ) goto badbase;
  S->set_hidden_segtype(true);
  S->update();
  if ( curClass.xtrnCnt ) {
    if ( (S = getseg(curClass.xtrnEA)) == NULL ) goto badbase;
    S->set_hidden_segtype(true);
    S->update();
  }

  curClass.extflg |= XFL_C_DONE;  // do not repeat datalabel destroyer :)
// change: method/fields format
#define SGEXPSZ (sizeof(SegInfo) - offsetof(SegInfo, varNode))
#define FMEXPSZ (sizeof(_FMid_) - offsetof(_FMid_, _UNUSED_ALING))
#define FLEXPSZ (sizeof(FieldInfo) - offsetof(FieldInfo, annNodes))
  uval_t  oldsize = sizeof(SegInfo) - FMEXPSZ - SGEXPSZ;

  for(int pos=-(int)curClass.MethodCnt; pos<=(int)curClass.FieldCnt; pos++) {
    union {
      SegInfo   s;
      FieldInfo f;
      _FMid_    id;
      uchar     _space[qmax(sizeof(SegInfo), sizeof(FieldInfo)) + 1];
    }u;

    if ( !pos ) {  // class node
      oldsize += (sizeof(FieldInfo) - FLEXPSZ) - (sizeof(SegInfo) - SGEXPSZ);
      continue;
    }

    if ( ClassNode.supval(pos, &u, sizeof(u)) != oldsize ) goto badbase;

    memmove((uchar *)&u.id + sizeof(u.id), &u.id._UNUSED_ALING,
            (size_t)oldsize - offsetof(_FMid_, _UNUSED_ALING));
    u.id._UNUSED_ALING = 0;
    u.id.utsign        = 0;

    if ( u.id.extflg & ~EFL__MASK ) goto badbase;
    u.id.extflg &= (EFL_NAMETYPE);

    if ( pos > 0 ) { // fields
      memset(&u.f.annNodes, 0, sizeof(u.f)-offsetof(FieldInfo, annNodes));
      ClassNode.supset(pos, &u.f, sizeof(u.f));
      continue;
    }

    // segments
    memset(&u.s.varNode, 0, sizeof(u.s) - offsetof(SegInfo, varNode));
    if ( u.s.thrNode && !netnode(u.s.thrNode).altval(0) ) {
      netnode(u.s.thrNode).kill();  // empty node (old format)
      u.s.thrNode = 0;
    }

    // have locvars?
    if ( u.s.DataSize ) {
      if ( (S = getseg(u.s.DataBase)) == NULL ) goto badbase;
      S->type = SEG_BSS;
      S->set_hidden_segtype(true);
      S->update();
    }

    // change: Exception format
    if ( u.s.excNode ) {
      register ushort i, j;
      netnode         enode(u.s.excNode);

      if ( (j = (ushort)enode.altval(0)) == 0 ) goto badbase;
      ea_t ea = u.s.startEA + u.s.CodeSize;
      i = 1;
      do {
        Exception exc;

        if ( enode.supval(i, &exc, sizeof(exc)) != sizeof(exc) ) goto badbase;

#ifdef __BORLANDC__
#if offsetof(Exception, filter.Ref)  != offsetof(Exception, filter.Name) || \
    offsetof(Exception, filter.Dscr) != offsetof(Exception, filter.Name) + 2
#error
#endif
#endif
        if ( !exc.filter.Name != !exc.filter.Dscr ) goto badbase;
        exc.filter.Ref = (exc.filter.Ref << 16) | exc.filter.Dscr; // was reverse order
        if ( exc.filter.Name == 0xFFFF ) ++exc.filter.Name;
        enode.supset(i, &exc, sizeof(exc));
        set_exception_xref(&u.s, exc, ea);
      }while ( ++i <= j );
    }
    ClassNode.supset(pos, &u.s, sizeof(u.s));
    //rename local variables (for references)
    if ( u.s.DataSize ) {
      int   i = u.s.DataSize;
      ea_t  ea = u.s.DataBase + i;
      do {
        char  str[MAXNAMELEN];
        qsnprintf(str, sizeof(str), "met%03u_slot%03u", u.s.id.Number, --i);
        --ea;
        if ( do_name_anyway(ea, str)) make_name_auto(ea );
        else hide_name(ea);
      }while ( i );
      coagulate_unused_data(&u.s);
    }
  } // for

//change format of string presentation in constant pool
  for(int pos = 0; (ushort)pos <= curClass.maxCPindex; pos++) {
    ConstOpis co;

    if ( constnode.supval(pos, &co, sizeof(co)) != sizeof(co) ) goto badbase;
    switch ( co.type ) {
      default:
        continue;

      case CONSTANT_Unicode:
        error("Base contain CONSTANT_Unicode, but it is removed from "
              "the standard in 1996 year and never normal loaded in IDA");

      case CONSTANT_Utf8:
        break;
    }
    uint32 v, n, i = pos << 16;
    if(   ((n = (uint32)constnode.altval(i)) & UPG12_BADMASK)
       || (v = n & ~UPG12_CLRMASK) == 0) goto badbase;
    if ( n & UPG12_EXTMASK ) v |= UPG12_EXTSET;
    if ( (n = (ushort)v) != 0 ) {
      register uchar *po = (uchar*)append_tmp_buffer(v);
      n *= sizeof(ushort);
      uint32 pos = 0;
      do {
        uint32 sz = n - pos;
        if ( sz > MAXSPECSIZE ) sz = MAXSPECSIZE;
        if ( constnode.supval(++i, &po[pos], sz) != sz ) goto badbase;
        constnode.supdel(i);
        pos += sz;
      }while ( pos < n );
      constnode.setblob(po, n, i & ~0xFFFF, BLOB_TAG);
      if ( !(v & UPG12_EXTSET) ) do {
#ifdef __BORLANDC__
#if ( sizeof(ushort) % 2) || (MAXSPECSIZE % 2 )
#error
#endif
#endif
        ushort cw = *(ushort *)&po[pos];
        if ( cw >= CHP_MAX ) {
          if ( !javaIdent(cw) ) goto extchar;
        } else if ( (uchar)cw <= CHP_MIN ) {
extchar:
          v |= UPG12_EXTSET;
          break;
        }
      }while ( (pos -= sizeof(ushort)) != 0 );
      v = upgrade_ResW(v);
    }
    constnode.altset(i, v);
    co._Sopstr = v; // my be not needed? (next also)
    constnode.supset(pos, &co, sizeof(co));
  }

// rename 'import' variables for refernces
  for(unsigned ip = 1; (ushort)ip <= curClass.xtrnCnt; ip++) {
    ConstOpis co;
    {
      register unsigned j;
      if(   (j = (unsigned)XtrnNode.altval(ip)) == 0
         || !LoadOpis((ushort)j, 0, &co)) goto badbase;
    }
    switch ( co.type ) {
      default:
        goto badbase;

      case CONSTANT_Class:
        if ( !(co.flag & HAS_CLSNAME) ) continue;
        break;
      case CONSTANT_InterfaceMethodref:
      case CONSTANT_Methodref:
        if ( (co.flag & NORM_METOD) != NORM_METOD ) continue;
        break;
      case CONSTANT_Fieldref:
        if ( (co.flag & NORM_FIELD) != NORM_FIELD ) continue;
        break;
    }
    make_new_name(co._name, co._subnam, co.type != CONSTANT_Class, ip);
  }

  if ( curClass.This.Dscr )
    make_new_name(curClass.This.Name, 0, (uchar)-1, (unsigned)curClass.startEA);

  return(_TO_VERSION);
}