コード例 #1
0
/* Initializes the environment */
void init_environment()
{
  int row, column; 

#if FITNESS_DEBUG
  printf("About to initialize environment\n"); 
#endif

  /* Initialize the environment */
  for (row=0; row < NUM_ENVIRONMENT_ROWS; row++)
    for (column=0; column < NUM_ENVIRONMENT_COLUMNS; column++) {
      environment[row][column].C_row = row; 
      environment[row][column].C_column = column; 
      environment[row][column].N_row = row-1; 
      environment[row][column].N_column = column; 
      environment[row][column].S_row = row+1; 
      environment[row][column].S_column = column; 
      environment[row][column].E_row = row; 
      environment[row][column].E_column = column+1; 
      environment[row][column].W_row = row; 
      environment[row][column].W_column = column-1; 
      environment[row][column].contains_soda_can = (knuth_random() <= 0.5) ? TRUE : FALSE;
    }

  /* Put robby at starting square 0,0. */ 
  
  robby_row = 0; 
  robby_column = 0; 

#if FITNESS_DEBUG
  printf("About to print the environment\n"); 
  print_environment(); 
#endif

}
コード例 #2
0
void
print_argument_stack(struct stack_s *stack)
{
   int num = 0;

   while (stack){
        struct closure_s *c = stack->content;
        printf("Arg element #%d: %s\n", num++, c ? c->term : "<mark>");
        if (c)
            print_environment(c->env);
        stack = stack->next;
   }
}
コード例 #3
0
ファイル: env.c プロジェクト: trws/flux-core
static int cmd_env (optparse_t *p, int ac, char *av[])
{
    int n = optparse_option_index (p);
    if (av && av[n]) {
        execvp (av[n], av+n); /* no return if sucessful */
        log_err_exit ("execvp (%s)", av[n]);
    } else {
        struct environment *env = optparse_get_data (p, "env");
        if (env == NULL)
            log_msg_exit ("flux-env: failed to get flux envirnoment!");
        print_environment (env);
    }
    return (0);
}
コード例 #4
0
ファイル: main.c プロジェクト: v09-software/btree-db
int main(int argc, char **argv)
{

	long i,count,op;
	if(argc!=2)
	{
		fprintf(stderr,"Usage: nessdb_benchmark <op>\n");
        	exit(1);
	}

	if(strcmp(argv[1],"add")==0)
		op=OP_ADD;
	else if(strcmp(argv[1],"get")==0)
		op=OP_GET;
	else if(strcmp(argv[1],"walk")==0)
		op=OP_WALK;
	else
	{
		printf("not supported op %s\n", argv[1]);
        	exit(1);
    	}


	srand(time(NULL));
	print_header();
	print_environment();

	db_init_test();
	if(op==OP_ADD)
		db_tests();
	else if(op==OP_WALK)
		db_read_seq_test();
	else if(op==OP_GET)
		db_read_random_test();
	
	btree_close(&btree);

	return 0;
}
コード例 #5
0
int
main(int argc, char **argv)
{
    unsigned opt;
    char *param, *filename=0, *endptr=0;
    unsigned short dbname=0xffff;
    int full=0;

    ham_u16_t names[1024];
    ham_size_t i, names_count=1024;
    ham_status_t st;
    ham_env_t *env;
    ham_db_t *db;

    ham_u32_t maj, min, rev;
    const char *licensee, *product;
    ham_get_license(&licensee, &product);
    ham_get_version(&maj, &min, &rev);

    getopts_init(argc, argv, "ham_info");

    while ((opt=getopts(&opts[0], &param))) {
        switch (opt) {
            case ARG_DBNAME:
                if (!param) {
                    printf("Parameter `dbname' is missing.\n");
                    return (-1);
                }
                dbname=(short)strtoul(param, &endptr, 0);
                if (endptr && *endptr) {
                    printf("Invalid parameter `dbname'; numerical value "
                           "expected.\n");
                    return (-1);
                }
                break;
            case ARG_FULL:
                full=1;
                break;
            case GETOPTS_PARAMETER:
                if (filename) {
                    printf("Multiple files specified. Please specify "
                           "only one filename.\n");
                    return (-1);
                }
                filename=param;
                break;
            case ARG_HELP:
                printf("hamsterdb %d.%d.%d - Copyright (C) 2005-2007 "
                       "Christoph Rupp ([email protected]).\n\n",
                       maj, min, rev);

                if (licensee[0]=='\0')
                    printf(
                       "This program is free software; you can redistribute "
                       "it and/or modify it\nunder the terms of the GNU "
                       "General Public License as published by the Free\n"
                       "Software Foundation; either version 2 of the License,\n"
                       "or (at your option) any later version.\n\n"
                       "See file COPYING.GPL2 and COPYING.GPL3 for License "
                       "information.\n\n");
                else
                    printf("Commercial version; licensed for %s (%s)\n\n",
                            licensee, product);

                printf("usage: ham_info [-db DBNAME] [-f] file\n");
                printf("usage: ham_info -h\n");
                printf("       -h:         this help screen (alias: --help)\n");
                printf("       -db DBNAME: only print info about "
                        "this database (alias: --dbname=<arg>)\n");
                printf("       -f:         print full information "
                        "(alias: --full)\n");
                return (0);
            default:
                printf("Invalid or unknown parameter `%s'. "
                       "Enter `ham_info --help' for usage.", param);
                return (-1);
        }
    }

    if (!filename) {
        printf("Filename is missing. Enter `ham_info --help' for usage.\n");
        return (-1);
    }

    /*
     * open the environment
     */
    st=ham_env_new(&env);
    if (st!=HAM_SUCCESS)
        error("ham_env_new", st);
    st=ham_env_open(env, filename, HAM_READ_ONLY);
    if (st==HAM_FILE_NOT_FOUND) {
        printf("File `%s' not found or unable to open it\n", filename);
        return (-1);
    }
    else if (st!=HAM_SUCCESS)
        error("ham_env_open", st);

    /*
     * print information about the environment
     */
    print_environment(env);

    /*
     * get a list of all databases
     */
    st=ham_env_get_database_names(env, names, &names_count);
    if (st!=HAM_SUCCESS)
        error("ham_env_get_database_names", st);

    /*
     * did the user specify a database name? if yes, show only this database
     */
    if (dbname!=0xffff) {
        st=ham_new(&db);
        if (st)
            error("ham_new", st);
    
        st=ham_env_open_db(env, db, dbname, 0, 0);
        if (st==HAM_DATABASE_NOT_FOUND) {
            printf("Database %u (0x%x) not found\n", dbname, dbname);
            return (-1);
        }
        else if (st)
            error("ham_env_open_db", st);
    
        print_database(db, dbname, full);
    
        st=ham_close(db, 0);
        if (st)
            error("ham_close", st);
        ham_delete(db);
    }
    else {
        /*
         * otherwise: for each database: print information about the database
         */
        for (i=0; i<names_count; i++) {
            st=ham_new(&db);
            if (st)
                error("ham_new", st);
    
            st=ham_env_open_db(env, db, names[i], 0, 0);
            if (st)
                error("ham_env_open_db", st);
    
            print_database(db, names[i], full);
    
            st=ham_close(db, 0);
            if (st)
                error("ham_close", st);
            ham_delete(db);
        }
    } 
    /*
     * clean up
     */
    st=ham_env_close(env, 0);
    if (st!=HAM_SUCCESS)
        error("ham_env_close", st);

    ham_env_delete(env);

    return (0);
}
コード例 #6
0
ファイル: gkd-main.c プロジェクト: Distrotech/gnome-keyring
int
main (int argc, char *argv[])
{
	/*
	 * The gnome-keyring startup is not as simple as I wish it could be.
	 *
	 * It's often started in the primordial stages of a session, where
	 * there's no DBus, and no proper X display. This is the strange world
	 * of PAM.
	 *
	 * When started with the --login option, we do as little initialization
	 * as possible. We expect a login password on the stdin, and unlock
	 * or create the login keyring.
	 *
	 * Then later we expect gnome-keyring-dameon to be run again with the
	 * --start option. This second gnome-keyring-daemon will hook the
	 * original daemon up with environment variables necessary to initialize
	 * itself and bring it into the session. This second daemon usually exits.
	 *
	 * Without either of these options, we follow a more boring and
	 * predictable startup.
	 */

	/*
	 * Before we do ANYTHING, we drop privileges so we don't become
	 * a security issue ourselves.
	 */
	gkd_capability_obtain_capability_and_drop_privileges ();

#ifdef WITH_STRICT
	g_setenv ("DBUS_FATAL_WARNINGS", "1", FALSE);
	if (!g_getenv ("G_DEBUG"))
		g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
#endif

#if !GLIB_CHECK_VERSION(2,35,0)
	g_type_init ();
#endif

#ifdef HAVE_LOCALE_H
	/* internationalisation */
	setlocale (LC_ALL, "");
#endif

#ifdef HAVE_GETTEXT
	bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
	textdomain (GETTEXT_PACKAGE);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
#endif

	egg_libgcrypt_initialize ();

	/* Send all warning or error messages to syslog */
	prepare_logging ();

	parse_arguments (&argc, &argv);

	/* The --version option. This is machine parseable output */
	if (run_version) {
		g_print ("gnome-keyring-daemon: %s\n", VERSION);
		g_print ("testing: %s\n",
#ifdef WITH_DEBUG
		         "enabled");
#else
		         "disabled");
#endif
		exit (0);
	}

	/* The --start option */
	if (run_for_start) {
		if (discover_other_daemon (initialize_daemon_at, TRUE)) {
			/*
			 * Another daemon was initialized, print out environment
			 * for any callers, and quit or go comatose.
			 */
			print_environment ();
			if (run_foreground)
				while (sleep(0x08000000) == 0);
			cleanup_and_exit (0);
		}

	/* The --replace option */
	} else if (run_for_replace) {
		discover_other_daemon (replace_daemon_at, FALSE);
		if (control_directory)
			g_message ("Replacing daemon, using directory: %s", control_directory);
		else
			g_message ("Could not find daemon to replace, staring normally");
	}

	/* Initialize the main directory */
	gkd_util_init_master_directory (control_directory);

	/* Initialize our daemon main loop and threading */
	loop = g_main_loop_new (NULL, FALSE);

	/* Initialize our control socket */
	if (!gkd_control_listen ())
		return FALSE;

	if (perform_unlock) {
		login_password = read_login_password (STDIN);
		atexit (clear_login_password);
	}

	/* The --login option. Delayed initialization */
	if (run_for_login) {
		timeout_id = g_timeout_add_seconds (LOGIN_TIMEOUT, (GSourceFunc) on_login_timeout, NULL);

	/* Not a login daemon. Startup stuff now.*/
	} else {
		/* These are things that can run before forking */
		if (!gkr_daemon_startup_steps (run_components))
			cleanup_and_exit (1);
	}

	signal (SIGPIPE, SIG_IGN);

	/* The whole forking and daemonizing dance starts here. */
	fork_and_print_environment();

	g_unix_signal_add (SIGTERM, on_signal_term, loop);
	g_unix_signal_add (SIGHUP, on_signal_term, loop);
	g_unix_signal_add (SIGUSR1, on_signal_usr1, loop);

	/* Prepare logging a second time, since we may be in a different process */
	prepare_logging();

	/* Remainder initialization after forking, if initialization not delayed */
	if (!run_for_login) {
		gkr_daemon_initialize_steps (run_components);

		/*
		 * Close stdout and so that the caller knows that we're
		 * all initialized, (when run in foreground mode).
		 *
		 * However since some logging goes to stdout, redirect that
		 * to stderr. We don't want the caller confusing that with
		 * valid output anyway.
		 */
		if (dup2 (2, 1) < 1)
			g_warning ("couldn't redirect stdout to stderr");

		g_debug ("initialization complete");
	}

	g_main_loop_run (loop);

	/* This wraps everything up in order */
	egg_cleanup_perform ();

	g_free (control_directory);

	g_debug ("exiting cleanly");
	return 0;
}
コード例 #7
0
ファイル: gkd-main.c プロジェクト: Distrotech/gnome-keyring
static void
fork_and_print_environment (void)
{
	int status;
	pid_t pid;
	int fd, i;

	if (run_foreground) {
		print_environment ();
		return;
	}

	pid = fork ();

	if (pid != 0) {

		/* Here we are in the initial process */

		if (run_daemonized) {

			/* Initial process, waits for intermediate child */
			if (pid == -1)
				exit (1);

			waitpid (pid, &status, 0);
			if (WEXITSTATUS (status) != 0)
				exit (WEXITSTATUS (status));

		} else {
			/* Not double forking */
			print_environment ();
		}

		/* The initial process exits successfully */
		exit (0);
	}

	if (run_daemonized) {

		/*
		 * Become session leader of a new session, process group leader of a new
		 * process group, and detach from the controlling TTY, so that SIGHUP is
		 * not sent to this process when the previous session leader dies
		 */
		setsid ();

		/* Double fork if need to daemonize properly */
		pid = fork ();

		if (pid != 0) {

			/* Here we are in the intermediate child process */

			/*
			 * This process exits, so that the final child will inherit
			 * init as parent to avoid zombies
			 */
			if (pid == -1)
				exit (1);

			/* We've done two forks. */
			print_environment ();

			/* The intermediate child exits */
			exit (0);
		}

	}

	/* Here we are in the resulting daemon or background process. */

	for (i = 0; i < 3; ++i) {
		fd = open ("/dev/null", O_RDONLY);
		sane_dup2 (fd, i);
		close (fd);
	}
}
コード例 #8
0
ファイル: gkd-main.c プロジェクト: fatman2021/mate-keyring
static void
fork_and_print_environment (void)
{
	int status;
	pid_t pid;
	int fd, i;

	if (run_foreground) {
		print_environment (getpid ());
		return;
	}

	pid = fork ();

	if (pid != 0) {

		/* Here we are in the initial process */

		if (run_daemonized) {

			/* Initial process, waits for intermediate child */
			if (pid == -1)
				exit (1);

			waitpid (pid, &status, 0);
			if (WEXITSTATUS (status) != 0)
				exit (WEXITSTATUS (status));

		} else {
			/* Not double forking, we know the PID */
			print_environment (pid);
		}

		/* The initial process exits successfully */
		exit (0);
	}

	if (run_daemonized) {

		/* Double fork if need to daemonize properly */
		pid = fork ();

		if (pid != 0) {

			/* Here we are in the intermediate child process */

			/*
			 * This process exits, so that the final child will inherit
			 * init as parent to avoid zombies
			 */
			if (pid == -1)
				exit (1);

			/* We've done two forks. Now we know the PID */
			print_environment (pid);

			/* The intermediate child exits */
			exit (0);
		}

	}

	/* Here we are in the resulting daemon or background process. */

	for (i = 0; i < 3; ++i) {
		fd = open ("/dev/null", O_RDONLY);
		sane_dup2 (fd, i);
		close (fd);
	}
}
コード例 #9
0
ファイル: main.c プロジェクト: danielsson/turtle-shell
/**
 * execute the checkEnv command.
 */
void cmd_check_env(char *args[ARGS_SIZE]) {
    int fd_descriptor_env_sort[2];
    int fd_descriptor_sort_pager[2];
    int fd_descriptor_grep_sort[2];
    pid_t env_child, sort_child, grep_child, pager_child;
    int grep = FALSE;
    int return_value;

    sighold(SIGCHLD);

    create_pipe(fd_descriptor_env_sort);
    create_pipe(fd_descriptor_sort_pager);
    create_pipe(fd_descriptor_grep_sort);
    env_child = fork();

    if (env_child == 0) {
        return_value = dup2(fd_descriptor_env_sort[PIPE_WRITE], STDOUT_FILENO);
        check_return_value(return_value, "Error: cannot dup2 1");

        close_all_pipes(fd_descriptor_env_sort, fd_descriptor_sort_pager, fd_descriptor_grep_sort);

        print_environment();
        exit(EXIT_SUCCESS);

    } else if (env_child == -1) {
        perror("Error forking.");
        exit(EXIT_FAILURE);
    }

    if(args[1] != NULL) {
        grep = TRUE;
        grep_child = fork();

        if(grep_child == 0) {
            return_value = dup2(fd_descriptor_env_sort[PIPE_READ], STDIN_FILENO);
            check_return_value(return_value, "Error: cannot dup2 2");

            return_value = dup2(fd_descriptor_grep_sort[PIPE_WRITE], STDOUT_FILENO);
            check_return_value(return_value, "Error: cannot dup2 3");

            close_all_pipes(fd_descriptor_env_sort, fd_descriptor_sort_pager, fd_descriptor_grep_sort);

            args[0] = "grep";

            return_value = execvp(args[0], args);
            check_return_value(return_value, "Error: execution failed.");
        } else if(grep_child == -1){
            perror("Error forking.");
            exit(EXIT_FAILURE);
        }
    }

    sort_child = fork();

    if (sort_child == 0) {
        char * argp[] = {"sort", NULL};

        if(grep == TRUE) {
            return_value = dup2(fd_descriptor_grep_sort[PIPE_READ], STDIN_FILENO);
            check_return_value(return_value, "Error: cannot dup2 3");
        } else {
            return_value = dup2(fd_descriptor_env_sort[PIPE_READ], STDIN_FILENO);
            check_return_value(return_value, "Error: cannot dup2 4");
        }
        return_value = dup2(fd_descriptor_sort_pager[PIPE_WRITE], STDOUT_FILENO);
        check_return_value(return_value, "Error: cannot dup2 5");

        close_all_pipes(fd_descriptor_env_sort, fd_descriptor_sort_pager, fd_descriptor_grep_sort);

        args[0] = "sort";

        return_value = execvp(args[0], argp);
        check_return_value(return_value, "Error: execution failed.");

    } else if (sort_child == -1) {
        perror("Error forking.");
        exit(EXIT_FAILURE);
    }

    pager_child = fork();

    if (pager_child == 0) {
        char * argp[] = {"less", NULL};
        return_value = dup2(fd_descriptor_sort_pager[PIPE_READ], STDIN_FILENO);
        check_return_value(return_value, "Error: cannot dup2 6");

        close_all_pipes(fd_descriptor_env_sort, fd_descriptor_sort_pager, fd_descriptor_grep_sort);

        if(getenv("PAGER") != NULL) {
            argp[0] = getenv("PAGER");
        }

        return_value = execvp(argp[0], argp);
        check_return_value(return_value, "Error: execution failed.");

    } else if (pager_child == -1) {
        perror("Error forking.");
        exit(EXIT_FAILURE);
    }

    close_all_pipes(fd_descriptor_env_sort, fd_descriptor_sort_pager, fd_descriptor_grep_sort);

    wait_for_child();
    wait_for_child();
    wait_for_child();
    if(grep == TRUE) wait_for_child();

    sigrelse(SIGCHLD);
}
コード例 #10
0
ファイル: flux.c プロジェクト: cigolabs/flux-core
static optparse_t * setup_optparse_parse_args (int argc, char *argv[])
{
    optparse_err_t e;
    struct optparse_option helpopt = {
        .name = "help", .key = 'h', .usage = "Display this message"
    };
    optparse_t *p = optparse_create ("flux");
    if (p == NULL)
        log_err_exit ("optparse_create");
    optparse_set (p, OPTPARSE_USAGE, "[OPTIONS] COMMAND ARGS");
    e = optparse_add_option_table (p, opts);
    if (e != OPTPARSE_SUCCESS)
        log_msg_exit ("optparse_add_option_table() failed");

    // Remove automatic `--help' in favor of our own usage() from above
    e = optparse_remove_option (p, "help");
    if (e != OPTPARSE_SUCCESS)
        log_msg_exit ("optparse_remove_option (\"help\")");
    e = optparse_add_option (p, &helpopt);
    if (e != OPTPARSE_SUCCESS)
        log_msg_exit ("optparse_add_option (\"help\")");

    // Don't print internal subcommands in --help (we print subcommands using
    //  emit_command_help() above.
    e = optparse_set (p, OPTPARSE_PRINT_SUBCMDS, 0);
    if (e != OPTPARSE_SUCCESS)
        log_msg_exit ("optparse_set (OPTPARSE_PRINT_SUBCMDS");

    register_builtin_subcommands (p);

    if (optparse_parse_args (p, argc, argv) < 0)
        exit (1);

    return (p);
}


int main (int argc, char *argv[])
{
    bool vopt = false;
    struct environment *env;
    optparse_t *p;
    const char *searchpath;
    const char *argv0 = argv[0];
    int flags = 0;

    log_init ("flux");

    p = setup_optparse_parse_args (argc, argv);

    if (!flux_is_installed ())
        flags |= CONF_FLAG_INTREE;
    optparse_set_data (p, "conf_flags", &flags);

    if (optparse_hasopt (p, "help")) {
        usage (p); // N.B. accesses "conf_flags"
        exit (0);
    }
    optind = optparse_optind (p);
    if (argc - optind == 0) {
        usage (p);
        exit (1);
    }
    vopt = optparse_hasopt (p, "verbose");

    /* prepare the environment 'env' that will be passed to subcommands.
     */
    env = environment_create ();

    /* Add PATH to env and prepend path to this executable if necessary.
     */
    setup_path (env, argv0);

    /* Prepend config values to env values.
     * Note special handling of lua ;; (default path).
     */
    environment_from_env (env, "LUA_CPATH", "", ';');
    environment_no_dedup_push_back (env, "LUA_CPATH", ";;");
    environment_push (env, "LUA_CPATH", flux_conf_get ("lua_cpath_add", flags));
    environment_push (env, "LUA_CPATH", getenv ("FLUX_LUA_CPATH_PREPEND"));

    environment_from_env (env, "LUA_PATH", "", ';');
    environment_no_dedup_push_back (env, "LUA_PATH", ";;");
    environment_push (env, "LUA_PATH", flux_conf_get ("lua_path_add", flags));
    environment_push (env, "LUA_PATH", getenv ("FLUX_LUA_PATH_PREPEND"));

    environment_from_env (env, "PYTHONPATH", "", ':');
    environment_push (env, "PYTHONPATH", flux_conf_get ("python_path", flags));
    environment_push (env, "PYTHONPATH", getenv ("FLUX_PYTHONPATH_PREPEND"));

    environment_from_env (env, "MANPATH", "", ':');
    environment_push (env, "MANPATH", flux_conf_get ("man_path", flags));

    environment_from_env (env, "FLUX_EXEC_PATH", "", ':');
    environment_push (env, "FLUX_EXEC_PATH",
                      flux_conf_get ("exec_path", flags));
    environment_push (env, "FLUX_EXEC_PATH", getenv ("FLUX_EXEC_PATH_PREPEND"));

    environment_from_env (env, "FLUX_CONNECTOR_PATH", "", ':');
    environment_push (env, "FLUX_CONNECTOR_PATH",
                      flux_conf_get ("connector_path", flags));
    environment_push (env, "FLUX_CONNECTOR_PATH",
                      getenv ("FLUX_CONNECTOR_PATH_PREPEND"));

    environment_from_env (env, "FLUX_MODULE_PATH", "", ':');
    environment_push (env, "FLUX_MODULE_PATH",
                      flux_conf_get ("module_path", flags));
    environment_push (env, "FLUX_MODULE_PATH",
                      getenv ("FLUX_MODULE_PATH_PREPEND"));

    /* Set FLUX_SEC_DIRECTORY, possibly to $HOME/.flux.
     */
    setup_keydir (env, flags);

    if (getenv ("FLUX_URI"))
        environment_from_env (env, "FLUX_URI", "", 0); /* pass-thru */

    environment_from_env (env, "FLUX_RC1_PATH",
                          flux_conf_get ("rc1_path", flags), 0);
    environment_from_env (env, "FLUX_RC3_PATH",
                          flux_conf_get ("rc3_path", flags), 0);
    environment_from_env (env, "FLUX_PMI_LIBRARY_PATH",
                          flux_conf_get ("pmi_library_path", flags), 0);
    environment_from_env (env, "FLUX_WRECK_LUA_PATTERN",
                          flux_conf_get ("wreck_lua_pattern", flags), 0);
    environment_from_env (env, "FLUX_WREXECD_PATH",
                          flux_conf_get ("wrexecd_path", flags), 0);

    environment_apply(env);
    optparse_set_data (p, "env", env);

    if (vopt)
        print_environment (env);
    if (optparse_get_subcommand (p, argv [optind])) {
        if (optparse_run_subcommand (p, argc, argv) < 0)
            exit (1);
    } else {
        searchpath = environment_get (env, "FLUX_EXEC_PATH");
        if (vopt)
            printf ("sub-command search path: %s\n", searchpath);
        exec_subcommand (searchpath, vopt, argv + optind);
    }

    environment_destroy (env);
    optparse_destroy (p);
    log_fini ();

    return 0;
}