コード例 #1
0
ファイル: troll.c プロジェクト: kevinwang/troll
int main(int argc, const char *argv[])
{
    if (argc == 1) {
        print_help_text();
        return 1;
    }
    argc--;
    argv++; // The command name is now the first argument
    return run_command(argc, argv);
}
コード例 #2
0
ファイル: main.c プロジェクト: pwithnall/bendy-bus
int
main (int argc, char *argv[])
{
	GError *error = NULL;
	GOptionContext *context;
	const gchar *simulation_filename, *introspection_filename;
	gchar *simulation_code, *introspection_xml;
	GPtrArray/*<DfsmObject>*/ *simulated_objects;
	guint i;
	gboolean found_unreachable_states = FALSE;

	/* Set up localisation. */
	setlocale (LC_ALL, "");
	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
	textdomain (GETTEXT_PACKAGE);

#if !GLIB_CHECK_VERSION (2, 35, 0)
	g_type_init ();
#endif
	g_set_application_name (_("D-Bus Simulator Lint"));

	/* Parse command line options */
	context = g_option_context_new (_("[simulation code file] [introspection XML file]"));
	g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
	g_option_context_set_summary (context, _("Checks the FSM simulation code for a D-Bus client–server conversation simulation."));

	if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
		g_printerr (_("Error parsing command line options: %s"), error->message);
		g_printerr ("\n");

		print_help_text (context);

		g_error_free (error);
		g_option_context_free (context);

		exit (STATUS_INVALID_OPTIONS);
	}

	/* Extract the simulation and the introspection filenames. */
	if (argc < 3) {
		g_printerr (_("Error parsing command line options: %s"), _("Simulation and introspection filenames must be provided"));
		g_printerr ("\n");

		print_help_text (context);

		g_option_context_free (context);

		exit (STATUS_INVALID_OPTIONS);
	}

	simulation_filename = argv[1];
	introspection_filename = argv[2];

	g_option_context_free (context);

	/* Load the files. */
	g_file_get_contents (simulation_filename, &simulation_code, NULL, &error);

	if (error != NULL) {
		g_printerr (_("Error loading simulation code from file ‘%s’: %s"), simulation_filename, error->message);
		g_printerr ("\n");

		g_error_free (error);

		exit (STATUS_UNREADABLE_FILE);
	}

	g_file_get_contents (introspection_filename, &introspection_xml, NULL, &error);

	if (error != NULL) {
		g_printerr (_("Error loading introspection XML from file ‘%s’: %s"), introspection_filename, error->message);
		g_printerr ("\n");

		g_error_free (error);
		g_free (simulation_code);

		exit (STATUS_UNREADABLE_FILE);
	}

	/* Build the DfsmObjects and thus check the simulation code. */
	simulated_objects = dfsm_object_factory_from_data (simulation_code, introspection_xml, &error);

	g_free (introspection_xml);
	g_free (simulation_code);

	if (error != NULL) {
		g_printerr (_("Error creating simulated DFSMs: %s"), error->message);
		g_printerr ("\n");

		g_error_free (error);

		exit (STATUS_INVALID_CODE);
	}

	/* Check the reachability of all of the states in each object. */
	for (i = 0; i < simulated_objects->len; i++) {
		DfsmObject *simulated_object;
		DfsmMachine *machine;
		GArray/*<DfsmStateReachability>*/ *reachability;
		DfsmMachineStateNumber state;

		simulated_object = DFSM_OBJECT (g_ptr_array_index (simulated_objects, i));
		machine = dfsm_object_get_machine (simulated_object);
		reachability = dfsm_machine_calculate_state_reachability (machine);

		for (state = 0; state < reachability->len; state++) {
			switch (g_array_index (reachability, DfsmStateReachability, state)) {
				case DFSM_STATE_UNREACHABLE:
					g_printerr (_("State ‘%s’ of object ‘%s’ is unreachable."),
					            dfsm_machine_get_state_name (machine, state),
					            dfsm_object_get_object_path (simulated_object));
					g_printerr ("\n");

					/* Note the error, but continue so that we detect any other unreachable states. */
					found_unreachable_states = TRUE;
					break;
				case DFSM_STATE_POSSIBLY_REACHABLE:
				case DFSM_STATE_REACHABLE:
					/* Nothing to do. */
					break;
				default:
					g_assert_not_reached ();
			}
		}

		g_array_unref (reachability);
	}

	g_ptr_array_unref (simulated_objects);

	/* Did we find at least one unreachable state? Yes? Shame. */
	if (found_unreachable_states == TRUE) {
		return STATUS_UNREACHABLE_STATES;
	}

	return STATUS_SUCCESS;
}
コード例 #3
0
ファイル: main.c プロジェクト: pwithnall/bendy-bus
int
main (int argc, char *argv[])
{
	GError *error = NULL;
	GOptionGroup *option_group;
	GOptionContext *context;
	const gchar *simulation_filename, *introspection_filename;
	gchar *simulation_code, *introspection_xml;
	MainData data;
	GPtrArray/*<DfsmObject>*/ *simulated_objects;
	const gchar *test_program_name;
	GPtrArray/*<string>*/ *test_program_argv;
	guint i;
	gchar *time_str, *command_line, *log_header, *seed_str;
	GDateTime *date_time;
	GFile *working_directory_file, *dbus_daemon_config_file;

	/* Set up localisation. */
	setlocale (LC_ALL, "");
	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
	textdomain (GETTEXT_PACKAGE);

#if !GLIB_CHECK_VERSION (2, 35, 0)
	g_type_init ();
#endif
	g_set_application_name (_("D-Bus Simulator"));

	/* Take a copy of the command line, for use in printing the log headers later. */
	command_line = g_strjoinv (" ", argv);

	/* Parse command line options */
	context = g_option_context_new (_("[simulation code file] [introspection XML file] -- [executable-file] [arguments]"));
	g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
	g_option_context_set_summary (context, _("Simulates the server in a D-Bus client–server conversation."));
	g_option_context_add_main_entries (context, main_entries, GETTEXT_PACKAGE);

	/* Logging option group */
	option_group = g_option_group_new ("logging", _("Logging Options:"), _("Show help options for output logging"), NULL, NULL);
	g_option_group_set_translation_domain (option_group, GETTEXT_PACKAGE);
	g_option_group_add_entries (option_group, logging_entries);
	g_option_context_add_group (context, option_group);

	/* Testing option group */
	option_group = g_option_group_new ("testing", _("Testing Options:"), _("Show help options for test runs and timeouts"), NULL, NULL);
	g_option_group_set_translation_domain (option_group, GETTEXT_PACKAGE);
	g_option_group_add_entries (option_group, testing_entries);
	g_option_context_add_group (context, option_group);

	/* Test program option group */
	option_group = g_option_group_new ("test-program", _("Test Program Options:"), _("Show help options for the program under test"), NULL, NULL);
	g_option_group_set_translation_domain (option_group, GETTEXT_PACKAGE);
	g_option_group_add_entries (option_group, test_program_entries);
	g_option_context_add_group (context, option_group);

	/* dbus-daemon option group */
	option_group = g_option_group_new ("dbus-daemon", _("D-Bus Daemon Options:"), _("Show help options for the dbus-daemon"), NULL, NULL);
	g_option_group_set_translation_domain (option_group, GETTEXT_PACKAGE);
	g_option_group_add_entries (option_group, dbus_daemon_entries);
	g_option_context_add_group (context, option_group);

	if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) {
		g_printerr (_("Error parsing command line options: %s"), error->message);
		g_printerr ("\n");

		print_help_text (context);

		g_error_free (error);
		g_option_context_free (context);
		g_free (command_line);

		exit (STATUS_INVALID_OPTIONS);
	}

	/* Extract the simulation and the introspection filenames. */
	if (argc < 3) {
		g_printerr (_("Error parsing command line options: %s"), _("Simulation and introspection filenames must be provided"));
		g_printerr ("\n");

		print_help_text (context);

		g_option_context_free (context);
		g_free (command_line);

		exit (STATUS_INVALID_OPTIONS);
	}

	simulation_filename = argv[1];
	introspection_filename = argv[2];

	/* Extract the remaining arguments */
	if (argc < 4) {
		g_printerr (_("Error parsing command line options: %s"), _("Test program must be provided"));
		g_printerr ("\n");

		print_help_text (context);

		g_option_context_free (context);
		g_free (command_line);

		exit (STATUS_INVALID_OPTIONS);
	}

	/* Work out where the test program's command line starts. g_option_context_parse() sometimes leaves the ‘--’ in argv. */
	if (strcmp (argv[3], "--") == 0) {
		i = 4;
	} else {
		i = 3;
	}

	test_program_name = argv[i++];
	test_program_argv = g_ptr_array_new_with_free_func (g_free);

	for (; i < (guint) argc; i++) {
		g_ptr_array_add (test_program_argv, g_strdup (argv[i]));
	}

	g_option_context_free (context);

	/* Set up logging. */
	dsim_logging_init (test_program_log_file, test_program_log_fd, dbus_daemon_log_file, dbus_daemon_log_fd, simulator_log_file, simulator_log_fd,
	                   &error);

	if (error != NULL) {
		g_printerr (_("Error setting up logging: %s"), error->message);
		g_printerr ("\n");

		g_error_free (error);
		g_free (command_line);

		exit (STATUS_LOGGING_PROBLEM);
	}

	/* Output a log header to each of the log streams. */
	date_time = g_date_time_new_now_utc ();
	time_str = g_date_time_format (date_time, "%F %TZ");
	g_date_time_unref (date_time);

	log_header = g_strdup_printf (_("Bendy Bus (number %s) left the depot at %s using command line: %s"), PACKAGE_VERSION, time_str, command_line);

	g_log (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, "%s", log_header);
	g_log (dsim_logging_get_domain_name (DSIM_LOG_DBUS_DAEMON), G_LOG_LEVEL_MESSAGE, "%s", log_header);
	g_log (dsim_logging_get_domain_name (DSIM_LOG_TEST_PROGRAM), G_LOG_LEVEL_MESSAGE, "%s", log_header);

	g_free (log_header);
	g_free (time_str);
	g_free (command_line);

	/* Set up the random number generator. */
	if (random_seed == 0) {
		random_seed = g_get_real_time ();
	}

	seed_str = g_strdup_printf ("%" G_GINT64_FORMAT, random_seed);
	g_message (_("Note: Setting random number generator seed to %s."), seed_str);
	g_free (seed_str);

	g_random_set_seed ((guint32) random_seed);

	/* Load the files. */
	g_file_get_contents (simulation_filename, &simulation_code, NULL, &error);

	if (error != NULL) {
		g_printerr (_("Error loading simulation code from file ‘%s’: %s"), simulation_filename, error->message);
		g_printerr ("\n");

		g_error_free (error);

		exit (STATUS_UNREADABLE_FILE);
	}

	g_file_get_contents (introspection_filename, &introspection_xml, NULL, &error);

	if (error != NULL) {
		g_printerr (_("Error loading introspection XML from file ‘%s’: %s"), introspection_filename, error->message);
		g_printerr ("\n");

		g_error_free (error);
		g_free (simulation_code);

		exit (STATUS_UNREADABLE_FILE);
	}

	/* Build the DfsmObjects. */
	simulated_objects = dfsm_object_factory_from_data (simulation_code, introspection_xml, &error);

	g_free (introspection_xml);
	g_free (simulation_code);

	if (error != NULL) {
		g_printerr (_("Error creating simulated DFSMs: %s"), error->message);
		g_printerr ("\n");

		g_error_free (error);

		exit (STATUS_INVALID_CODE);
	}

	/* Prepare the main data struct, which will last for the lifetime of the program. */
	data.main_loop = g_main_loop_new (NULL, FALSE);
	data.exit_status = STATUS_SUCCESS;
	data.exit_signal = EXIT_SIGNAL_INVALID;
	data.test_program = NULL;
	data.connection = NULL;
	data.simulated_objects = g_ptr_array_ref (simulated_objects);
	data.outstanding_registration_callbacks = 0;
	data.test_run_inactivity_timeout_id = 0;
	data.test_program_spawn_end_signal = 0;
	data.test_program_process_died_signal = 0;
	data.test_program_sigkill_timeout_id = 0;

	if (run_infinitely == TRUE || (run_iters == 0 && run_time == 0)) {
		data.num_test_runs_remaining = -1;
	} else {
		data.num_test_runs_remaining = run_iters;
	}

	g_ptr_array_unref (simulated_objects);

	/* Store the test program name and argv, since we can only spawn it once we know the bus address. */
	data.test_program_name = g_strdup (test_program_name);
	data.test_program_argv = g_ptr_array_ref (test_program_argv);

	g_ptr_array_unref (test_program_argv);

	/* Set up signal handlers for SIGINT and SIGTERM so that we can close gracefully. */
	g_unix_signal_add (SIGINT, (GSourceFunc) sigint_handler_cb, &data);
	g_unix_signal_add (SIGTERM, (GSourceFunc) sigterm_handler_cb, &data);

	/* Create a working directory. */
	prepare_dbus_daemon_working_directory (&(data.working_directory_file), &working_directory_file, &dbus_daemon_config_file, &error);

	if (error != NULL) {
		g_printerr (_("Error creating dbus-daemon working directory: %s"), error->message);
		g_printerr ("\n");

		g_error_free (error);
		main_data_clear (&data);
		dsim_logging_finalise ();

		exit (STATUS_TMP_DIR_ERROR);
	}

	/* Start up our own private dbus-daemon instance. */
	data.dbus_daemon = dsim_dbus_daemon_new (working_directory_file, dbus_daemon_config_file);
	data.dbus_address = NULL;

	g_object_unref (dbus_daemon_config_file);
	g_object_unref (working_directory_file);

	g_signal_connect (data.dbus_daemon, "process-died", (GCallback) dbus_daemon_died_cb, &data);
	g_signal_connect (data.dbus_daemon, "notify::bus-address", (GCallback) dbus_daemon_notify_bus_address_cb, &data);

	dsim_program_wrapper_spawn (DSIM_PROGRAM_WRAPPER (data.dbus_daemon), &error);

	if (error != NULL) {
		g_printerr (_("Error spawning private dbus-daemon instance: %s"), error->message);
		g_printerr ("\n");

		g_error_free (error);
		main_data_clear (&data);
		dsim_logging_finalise ();

		exit (STATUS_DAEMON_SPAWN_ERROR);
	}

	/* Start the main loop and wait for the dbus-daemon to send us its address. */
	g_main_loop_run (data.main_loop);

	/* Free the main data struct. */
	main_data_clear (&data);
	dsim_logging_finalise ();

	if (data.exit_signal != EXIT_SIGNAL_INVALID) {
		struct sigaction action;

		/* Propagate the signal to the default handler. */
		action.sa_handler = SIG_DFL;
		sigemptyset (&action.sa_mask);
		action.sa_flags = 0;

		sigaction (data.exit_signal, &action, NULL);

		kill (getpid (), data.exit_signal);
	}

	return data.exit_status;
}
コード例 #4
0
ファイル: daemonic.c プロジェクト: maildrop/daemonic
int entry_point( int argc , char* argv[] )
{
  if( ! ( 1 < argc ) ){
    /* オプションが足りない */
    print_help_text(argv[0]);
    return EXIT_SUCCESS;
  }

  /* まず一段階目のfork では SIGCHLD を 無視する  */
  {
    struct sigaction sa = {{0}}; 
    sa.sa_handler = SIG_IGN;
    sa.sa_flags = SA_NOCLDWAIT;
    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
      return EXIT_FAILURE;
    }
  }

  {
    const pid_t pid = fork();
    if( pid < 0 ){ // fork fail.
      perror( "fork faild" );
      return EXIT_FAILURE;
    }
    
    if( 0 != pid ){
      return EXIT_SUCCESS;
    }

    /* セッショングループを作り直して端末グループから外れる  */
    assert( 0 == pid && "the process is child process.");
    if( -1 == setsid() ){
      perror("create new session");
    }
  }

  /* パイプを作成する */
  int logger_pipes[2] = {-1,-1};
  if( pipe( logger_pipes ) ){
    perror( "pipe()" );
    return EXIT_FAILURE;
  }

  assert( 0 <=logger_pipes[0] );
  assert( 0 <=logger_pipes[1] );

  /* ログを書きだす先の プロセスを作成する */
  const pid_t logger_pid = fork();
  
  if( -1 == logger_pid ){
    perror( "fork() faild");
    VERIFY( 0 == close( logger_pipes[WRITE_SIDE] ));
    VERIFY( 0 == close( logger_pipes[READ_SIDE] ));
    abort();
  }

  if( 0 == logger_pid){
    VERIFY( 0 == close( logger_pipes[WRITE_SIDE] ));
    exec_logger_process( logger_pipes[READ_SIDE] );
    return EXIT_FAILURE;
  }else{
    VERIFY( 0 == close( logger_pipes[READ_SIDE] ));

    /* 標準入力を /dev/null に置き換える */
    {
      int null_in = open( "/dev/null" , O_RDONLY );
      if( -1 == null_in ){
        return EXIT_FAILURE;
      }
      int null_out = open( "/dev/null" , O_WRONLY );
      if( -1 == null_out ){
        return EXIT_FAILURE;
      }
      int stdin_dup  = dup( STDIN_FILENO );
      int stdout_dup = dup( STDOUT_FILENO );
      int stderr_dup = dup( STDERR_FILENO );
      VERIFY( dup2( null_in , STDIN_FILENO ) == STDIN_FILENO );
      VERIFY( dup2( null_out , STDOUT_FILENO ) == STDOUT_FILENO);
      VERIFY( dup2( null_out , STDERR_FILENO ) == STDERR_FILENO );
      
      VERIFY( 0 == close( stdin_dup  ) );
      VERIFY( 0 == close( stdout_dup ) );
      VERIFY( 0 == close( stderr_dup ) );
      
      VERIFY( 0 == close( null_in ));
      VERIFY( 0 == close( null_out ));
    }
    
    struct process_param param = { logger_pipes[WRITE_SIDE] ,NULL};

    char* pid_file_path = malloc( sizeof(char) * PATH_MAX );

    if( pid_file_path ){
      // TODO ここの PID_FILE_PATH の作り方、もうちょっと注意が必要 
      char *p = strrchr( argv[0] , '/' ); 
      if( p ){
        p++;
        p = (('\0' == *p) ? NULL : p);
      }else{
        p = argv[0];
      }
      VERIFY( 0 < snprintf( pid_file_path, sizeof( char ) * PATH_MAX , "/tmp/%s.pid" ,  (p)?(p): argv[0] ) );
      param.pid_file_path = pid_file_path;
      
      const size_t params_len = argc;
      char**params = malloc( sizeof(char*) * params_len );
      
      if( params ){
        // params に strdup で引数を積んでいく
        for( size_t i = 0 ; i < (params_len -1); ++i ){
          params[i] = strdup( argv[ i + 1] );
        }
        params[params_len - 1] = NULL;
        
        if( EXIT_SUCCESS != start_process(param, params[0], params ) ){
          // TODO spawn 失敗した
        }
        
        for( size_t i = 0;  i < params_len ; ++i ){
          if( params[i] ){
            free( params[i] );
          }
        }
        free( params );  
      }
      free( pid_file_path );
    }

    VERIFY( 0 == close( logger_pipes[WRITE_SIDE] ));
  }
  return EXIT_SUCCESS;
}