int
main (int argc _GL_UNUSED, char *argv[])
{
  set_program_name (argv[0]);

#if ENABLE_NLS
  /* Clean up environment.  */
  unsetenv ("LANGUAGE");
  unsetenv ("LC_ALL");
  unsetenv ("LC_MESSAGES");
  unsetenv ("LC_CTYPE");
  unsetenv ("LANG");
  unsetenv ("OUTPUT_CHARSET");

  /* This program part runs in a French UTF-8 locale.  It uses
     the test-quotearg.mo message catalog.  */
  {
    const char *locale_name = getenv ("LOCALE");

    if (locale_name != NULL && strcmp (locale_name, "none") != 0
        && setenv ("LC_ALL", locale_name, 1) == 0
        && setlocale (LC_ALL, "") != NULL)
      {
        textdomain ("test-quotearg");
        bindtextdomain ("test-quotearg", getenv ("LOCALEDIR"));

        set_quoting_style (NULL, locale_quoting_style);
        compare_strings (use_quotearg_buffer, &locale_results[0].group1, false);
        compare_strings (use_quotearg, &locale_results[0].group2, false);
        compare_strings (use_quotearg_colon, &locale_results[0].group3, false);

        set_quoting_style (NULL, clocale_quoting_style);
        compare_strings (use_quotearg_buffer, &locale_results[1].group1, false);
        compare_strings (use_quotearg, &locale_results[1].group2, false);
        compare_strings (use_quotearg_colon, &locale_results[1].group3, false);

        quotearg_free ();
        return 0;
      }
  }

  fputs ("Skipping test: no french Unicode locale is installed\n", stderr);
  return 77;
#else
  fputs ("Skipping test: internationalization is disabled\n", stderr);
  return 77;
#endif /* ENABLE_NLS */
}
Beispiel #2
0
static void
prepare_symbols (void)
{
  MUSCLE_INSERT_INT ("tokens_number", ntokens);
  MUSCLE_INSERT_INT ("nterms_number", nvars);
  MUSCLE_INSERT_INT ("symbols_number", nsyms);
  MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number);
  MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number);

  muscle_insert_symbol_number_table ("translate",
                                     token_translations,
                                     token_translations[0],
                                     1, max_user_token_number + 1);

  /* tname -- token names.  */
  {
    int i;
    /* We assume that the table will be output starting at column 2. */
    int j = 2;
    struct quoting_options *qo = clone_quoting_options (0);
    set_quoting_style (qo, c_quoting_style);
    set_quoting_flags (qo, QA_SPLIT_TRIGRAPHS);
    for (i = 0; i < nsyms; i++)
      {
        char *cp = quotearg_alloc (symbols[i]->tag, -1, qo);
        /* Width of the next token, including the two quotes, the
           comma and the space.  */
        int width = strlen (cp) + 2;

        if (j + width > 75)
          {
            obstack_sgrow (&format_obstack, "\n ");
            j = 1;
          }

        if (i)
          obstack_1grow (&format_obstack, ' ');
        obstack_escape (&format_obstack, cp);
        free (cp);
        obstack_1grow (&format_obstack, ',');
        j += width;
      }
    free (qo);
    obstack_sgrow (&format_obstack, " ]b4_null[");

    /* Finish table and store. */
    muscle_insert ("tname", obstack_finish0 (&format_obstack));
  }

  /* Output YYTOKNUM. */
  {
    int i;
    int *values = xnmalloc (ntokens, sizeof *values);
    for (i = 0; i < ntokens; ++i)
      values[i] = symbols[i]->user_token_number;
    muscle_insert_int_table ("toknum", values,
                             values[0], 1, ntokens);
    free (values);
  }
}
Beispiel #3
0
int
main (int argc, char *argv[])
{
  set_program_name (argv[0]);
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  bindtextdomain ("bison-runtime", LOCALEDIR);
  textdomain (PACKAGE);

  {
    char const *cp = getenv ("LC_CTYPE");
    if (cp && STREQ (cp, "C"))
      set_custom_quoting (&quote_quoting_options, "'", "'");
    else
      set_quoting_style (&quote_quoting_options, locale_quoting_style);
  }

  atexit (close_stdout);

  uniqstrs_new ();
  muscle_init ();
  complain_init ();

  getargs (argc, argv);

  timevar_report = trace_flag & trace_time;
  init_timevar ();
  timevar_start (TV_TOTAL);

  if (trace_flag & trace_bitsets)
    bitset_stats_enable ();

  /* Read the input.  Copy some parts of it to FGUARD, FACTION, FTABLE
     and FATTRS.  In file reader.c.  The other parts are recorded in
     the grammar; see gram.h.  */

  timevar_push (TV_READER);
  reader ();
  timevar_pop (TV_READER);

  if (complaint_status == status_complaint)
    goto finish;

  /* Find useless nonterminals and productions and reduce the grammar. */
  timevar_push (TV_REDUCE);
  reduce_grammar ();
  timevar_pop (TV_REDUCE);

  /* Record other info about the grammar.  In files derives and
     nullable.  */
  timevar_push (TV_SETS);
  derives_compute ();
  nullable_compute ();
  timevar_pop (TV_SETS);

  /* Compute LR(0) parser states.  See state.h for more info.  */
  timevar_push (TV_LR0);
  generate_states ();
  timevar_pop (TV_LR0);

  /* Add lookahead sets to parser states.  Except when LALR(1) is
     requested, split states to eliminate LR(1)-relative
     inadequacies.  */
  ielr ();

  /* Find and record any conflicts: places where one token of
     lookahead is not enough to disambiguate the parsing.  In file
     conflicts.  Also resolve s/r conflicts based on precedence
     declarations.  */
  timevar_push (TV_CONFLICTS);
  conflicts_solve ();
  if (!muscle_percent_define_flag_if ("lr.keep-unreachable-state"))
    {
      state_number *old_to_new = xnmalloc (nstates, sizeof *old_to_new);
      state_number nstates_old = nstates;
      state_remove_unreachable_states (old_to_new);
      lalr_update_state_numbers (old_to_new, nstates_old);
      conflicts_update_state_numbers (old_to_new, nstates_old);
      free (old_to_new);
    }
  conflicts_print ();
  timevar_pop (TV_CONFLICTS);

  /* Compute the parser tables.  */
  timevar_push (TV_ACTIONS);
  tables_generate ();
  timevar_pop (TV_ACTIONS);

  grammar_rules_useless_report (_("rule useless in parser due to conflicts"));

  print_precedence_warnings ();

  /* Output file names. */
  compute_output_file_names ();

  /* Output the detailed report on the grammar.  */
  if (report_flag)
    {
      timevar_push (TV_REPORT);
      print_results ();
      timevar_pop (TV_REPORT);
    }

  /* Output the graph.  */
  if (graph_flag)
    {
      timevar_push (TV_GRAPH);
      print_graph ();
      timevar_pop (TV_GRAPH);
    }

  /* Output xml.  */
  if (xml_flag)
    {
      timevar_push (TV_XML);
      print_xml ();
      timevar_pop (TV_XML);
    }

  /* Stop if there were errors, to avoid trashing previous output
     files.  */
  if (complaint_status == status_complaint)
    goto finish;

  /* Lookahead tokens are no longer needed. */
  timevar_push (TV_FREE);
  lalr_free ();
  timevar_pop (TV_FREE);

  /* Output the tables and the parser to ftable.  In file output.  */
  timevar_push (TV_PARSER);
  output ();
  timevar_pop (TV_PARSER);

  timevar_push (TV_FREE);
  nullable_free ();
  derives_free ();
  tables_free ();
  states_free ();
  reduce_free ();
  conflicts_free ();
  grammar_free ();
  output_file_names_free ();

  /* The scanner memory cannot be released right after parsing, as it
     contains things such as user actions, prologue, epilogue etc.  */
  gram_scanner_free ();
  muscle_free ();
  uniqstrs_free ();
  code_scanner_free ();
  skel_scanner_free ();
  quotearg_free ();
  timevar_pop (TV_FREE);

  if (trace_flag & trace_bitsets)
    bitset_stats_dump (stderr);

 finish:

  /* Stop timing and print the times.  */
  timevar_stop (TV_TOTAL);
  timevar_print (stderr);

  cleanup_caret ();

  return complaint_status ? EXIT_FAILURE : EXIT_SUCCESS;
}
Beispiel #4
0
/* Initializes the sh_quoting_options variable.  */
static void
init_sh_quoting_options ()
{
  sh_quoting_options = clone_quoting_options (NULL);
  set_quoting_style (sh_quoting_options, shell_quoting_style);
}
Beispiel #5
0
int
main (int argc _GL_UNUSED, char *argv[])
{
  int i;
  bool ascii_only = MB_CUR_MAX == 1 && !isprint ((unsigned char) LQ[0]);

  set_program_name (argv[0]);

  /* This part of the program is hard-wired to the C locale since it
     does not call setlocale.  However, according to POSIX, the use of
     8-bit bytes in a character context in the C locale gives
     unspecified results (that is, the C locale charset is allowed to
     be unibyte with 8-bit bytes rejected [ASCII], unibyte with 8-bit
     bytes being characters [often ISO-8859-1], or multibyte [often
     UTF-8]).  We assume that the latter two cases will be
     indistinguishable in this test - that is, the LQ and RQ sequences
     will pass through unchanged in either type of charset.  So when
     testing for quoting of str7, use the ascii_only flag to decide
     what to expect for the 8-bit data being quoted.  */
  ASSERT (!isprint ('\033'));
  for (i = literal_quoting_style; i <= clocale_quoting_style; i++)
    {
      set_quoting_style (NULL, i);
      compare_strings (use_quotearg_buffer, &results_g[i].group1, ascii_only);
      compare_strings (use_quotearg, &results_g[i].group2, ascii_only);
      if (i == c_quoting_style)
        compare_strings (use_quote_double_quotes, &results_g[i].group2,
                         ascii_only);
      compare_strings (use_quotearg_colon, &results_g[i].group3, ascii_only);
    }

  set_quoting_style (NULL, literal_quoting_style);
  ASSERT (set_quoting_flags (NULL, QA_ELIDE_NULL_BYTES) == 0);
  compare_strings (use_quotearg_buffer, &flag_results[0].group1, ascii_only);
  compare_strings (use_quotearg, &flag_results[0].group2, ascii_only);
  compare_strings (use_quotearg_colon, &flag_results[0].group3, ascii_only);

  set_quoting_style (NULL, c_quoting_style);
  ASSERT (set_quoting_flags (NULL, QA_ELIDE_OUTER_QUOTES)
          == QA_ELIDE_NULL_BYTES);
  compare_strings (use_quotearg_buffer, &flag_results[1].group1, ascii_only);
  compare_strings (use_quotearg, &flag_results[1].group2, ascii_only);
  compare_strings (use_quote_double_quotes, &flag_results[1].group2,
                   ascii_only);
  compare_strings (use_quotearg_colon, &flag_results[1].group3, ascii_only);

  ASSERT (set_quoting_flags (NULL, QA_SPLIT_TRIGRAPHS)
          == QA_ELIDE_OUTER_QUOTES);
  compare_strings (use_quotearg_buffer, &flag_results[2].group1, ascii_only);
  compare_strings (use_quotearg, &flag_results[2].group2, ascii_only);
  compare_strings (use_quote_double_quotes, &flag_results[2].group2,
                   ascii_only);
  compare_strings (use_quotearg_colon, &flag_results[2].group3, ascii_only);

  ASSERT (set_quoting_flags (NULL, 0) == QA_SPLIT_TRIGRAPHS);

  for (i = 0; i < sizeof custom_quotes / sizeof *custom_quotes; ++i)
    {
      set_custom_quoting (NULL,
                          custom_quotes[i][0], custom_quotes[i][1]);
      compare_strings (use_quotearg_buffer, &custom_results[i].group1,
                       ascii_only);
      compare_strings (use_quotearg, &custom_results[i].group2, ascii_only);
      compare_strings (use_quotearg_colon, &custom_results[i].group3,
                       ascii_only);
    }

#if ENABLE_NLS
  /* Clean up environment.  */
  unsetenv ("LANGUAGE");
  unsetenv ("LC_ALL");
  unsetenv ("LC_MESSAGES");
  unsetenv ("LC_CTYPE");
  unsetenv ("LANG");
  unsetenv ("OUTPUT_CHARSET");

  /* This program part runs in a French UTF-8 locale.  It uses
     the test-quotearg.mo message catalog.  */
  {
    const char *locale_name = getenv ("LOCALE");

    if (locale_name != NULL && strcmp (locale_name, "none") != 0
        && setenv ("LC_ALL", locale_name, 1) == 0
        && setlocale (LC_ALL, "") != NULL)
      {
        textdomain ("test-quotearg");
        bindtextdomain ("test-quotearg", getenv ("LOCALEDIR"));

        set_quoting_style (NULL, locale_quoting_style);
        compare_strings (use_quotearg_buffer, &locale_results[0].group1, false);
        compare_strings (use_quotearg, &locale_results[0].group2, false);
        compare_strings (use_quotearg_colon, &locale_results[0].group3, false);

        set_quoting_style (NULL, clocale_quoting_style);
        compare_strings (use_quotearg_buffer, &locale_results[1].group1, false);
        compare_strings (use_quotearg, &locale_results[1].group2, false);
        compare_strings (use_quotearg_colon, &locale_results[1].group3, false);
      }
  }
#endif /* ENABLE_NLS */

  quotearg_free ();
  return 0;
}
int
main (int argc _GL_UNUSED, char *argv[])
{
  int i;
  bool ascii_only = MB_CUR_MAX == 1 && !isprint ((unsigned char) LQ[0]);

  set_program_name (argv[0]);

  /* This part of the program is hard-wired to the C locale since it
     does not call setlocale.  However, according to POSIX, the use of
     8-bit bytes in a character context in the C locale gives
     unspecified results (that is, the C locale charset is allowed to
     be unibyte with 8-bit bytes rejected [ASCII], unibyte with 8-bit
     bytes being characters [often ISO-8859-1], or multibyte [often
     UTF-8]).  We assume that the latter two cases will be
     indistinguishable in this test - that is, the LQ and RQ sequences
     will pass through unchanged in either type of charset.  So when
     testing for quoting of str7, use the ascii_only flag to decide
     what to expect for the 8-bit data being quoted.  */
  ASSERT (!isprint ('\033'));
  for (i = literal_quoting_style; i <= clocale_quoting_style; i++)
    {
      set_quoting_style (NULL, (enum quoting_style) i);
      compare_strings (use_quotearg_buffer, &results_g[i].group1, ascii_only);
      compare_strings (use_quotearg, &results_g[i].group2, ascii_only);
      if (i == c_quoting_style)
        compare_strings (use_quote_double_quotes, &results_g[i].group2,
                         ascii_only);
      compare_strings (use_quotearg_colon, &results_g[i].group3, ascii_only);
    }

  set_quoting_style (NULL, literal_quoting_style);
  ASSERT (set_quoting_flags (NULL, QA_ELIDE_NULL_BYTES) == 0);
  compare_strings (use_quotearg_buffer, &flag_results[0].group1, ascii_only);
  compare_strings (use_quotearg, &flag_results[0].group2, ascii_only);
  compare_strings (use_quotearg_colon, &flag_results[0].group3, ascii_only);

  set_quoting_style (NULL, c_quoting_style);
  ASSERT (set_quoting_flags (NULL, QA_ELIDE_OUTER_QUOTES)
          == QA_ELIDE_NULL_BYTES);
  compare_strings (use_quotearg_buffer, &flag_results[1].group1, ascii_only);
  compare_strings (use_quotearg, &flag_results[1].group2, ascii_only);
  compare_strings (use_quote_double_quotes, &flag_results[1].group2,
                   ascii_only);
  compare_strings (use_quotearg_colon, &flag_results[1].group3, ascii_only);

  ASSERT (set_quoting_flags (NULL, QA_SPLIT_TRIGRAPHS)
          == QA_ELIDE_OUTER_QUOTES);
  compare_strings (use_quotearg_buffer, &flag_results[2].group1, ascii_only);
  compare_strings (use_quotearg, &flag_results[2].group2, ascii_only);
  compare_strings (use_quote_double_quotes, &flag_results[2].group2,
                   ascii_only);
  compare_strings (use_quotearg_colon, &flag_results[2].group3, ascii_only);

  ASSERT (set_quoting_flags (NULL, 0) == QA_SPLIT_TRIGRAPHS);

  for (i = 0; i < sizeof custom_quotes / sizeof *custom_quotes; ++i)
    {
      set_custom_quoting (NULL,
                          custom_quotes[i][0], custom_quotes[i][1]);
      compare_strings (use_quotearg_buffer, &custom_results[i].group1,
                       ascii_only);
      compare_strings (use_quotearg, &custom_results[i].group2, ascii_only);
      compare_strings (use_quotearg_colon, &custom_results[i].group3,
                       ascii_only);
    }

  quotearg_free ();
  return 0;
}
int
main (int argc _GL_UNUSED, char *argv[])
{
  int i;
  bool ascii_only = MB_CUR_MAX == 1 && !isprint ((unsigned char) LQ[0]);

  set_program_name (argv[0]);

  /* This part of the program is hard-wired to the C locale since it
     does not call setlocale.  However, according to POSIX, the use of
     8-bit bytes in a character context in the C locale gives
     unspecified results (that is, the C locale charset is allowed to
     be unibyte with 8-bit bytes rejected [ASCII], unibyte with 8-bit
     bytes being characters [often ISO-8859-1], or multibyte [often
     UTF-8]).  We assume that the latter two cases will be
     indistinguishable in this test - that is, the LQ and RQ sequences
     will pass through unchanged in either type of charset.  So when
     testing for quoting of str7, use the ascii_only flag to decide
     what to expect for the 8-bit data being quoted.  */
  ASSERT (!isprint ('\033'));
  for (i = literal_quoting_style; i <= clocale_quoting_style; i++)
    {
      set_quoting_style (NULL, (enum quoting_style) i);
      if (!(i == locale_quoting_style || i == clocale_quoting_style)
          || (strcmp (locale_charset (), "ASCII") == 0
              || strcmp (locale_charset (), "ANSI_X3.4-1968") == 0))
        {
          compare_strings (use_quotearg_buffer, &results_g[i].group1,
                           ascii_only);
          compare_strings (use_quotearg, &results_g[i].group2,
                           ascii_only);
          if (i == c_quoting_style)
            compare_strings (use_quote_double_quotes, &results_g[i].group2,
                             ascii_only);
          compare_strings (use_quotearg_colon, &results_g[i].group3,
                           ascii_only);
        }
    }

  set_quoting_style (NULL, literal_quoting_style);
  ASSERT (set_quoting_flags (NULL, QA_ELIDE_NULL_BYTES) == 0);
  compare_strings (use_quotearg_buffer, &flag_results[0].group1, ascii_only);
  compare_strings (use_quotearg, &flag_results[0].group2, ascii_only);
  compare_strings (use_quotearg_colon, &flag_results[0].group3, ascii_only);

  set_quoting_style (NULL, c_quoting_style);
  ASSERT (set_quoting_flags (NULL, QA_ELIDE_OUTER_QUOTES)
          == QA_ELIDE_NULL_BYTES);
  compare_strings (use_quotearg_buffer, &flag_results[1].group1, ascii_only);
  compare_strings (use_quotearg, &flag_results[1].group2, ascii_only);
  compare_strings (use_quote_double_quotes, &flag_results[1].group2,
                   ascii_only);
  compare_strings (use_quotearg_colon, &flag_results[1].group3, ascii_only);

  ASSERT (set_quoting_flags (NULL, QA_SPLIT_TRIGRAPHS)
          == QA_ELIDE_OUTER_QUOTES);
  compare_strings (use_quotearg_buffer, &flag_results[2].group1, ascii_only);
  compare_strings (use_quotearg, &flag_results[2].group2, ascii_only);
  compare_strings (use_quote_double_quotes, &flag_results[2].group2,
                   ascii_only);
  compare_strings (use_quotearg_colon, &flag_results[2].group3, ascii_only);

  ASSERT (set_quoting_flags (NULL, 0) == QA_SPLIT_TRIGRAPHS);

  for (i = 0; i < sizeof custom_quotes / sizeof *custom_quotes; ++i)
    {
      set_custom_quoting (NULL,
                          custom_quotes[i][0], custom_quotes[i][1]);
      compare_strings (use_quotearg_buffer, &custom_results[i].group1,
                       ascii_only);
      compare_strings (use_quotearg, &custom_results[i].group2, ascii_only);
      compare_strings (use_quotearg_colon, &custom_results[i].group3,
                       ascii_only);
    }

  {
    /* Trigger the bug whereby quotearg_buffer would read beyond the NUL
       that defines the end of the string being quoted.  Use an input
       string whose NUL is the last byte before an unreadable page.  */
    char *z = zerosize_ptr ();

    if (z)
      {
        size_t q_len = 1024;
        char *q = malloc (q_len + 1);
        char buf[10];
        memset (q, 'Q', q_len);
        q[q_len] = 0;

        /* Z points to the boundary between a readable/writable page
           and one that is neither readable nor writable.  Position
           our string so its NUL is at the end of the writable one.  */
        char const *str = "____";
        size_t s_len = strlen (str);
        z -= s_len + 1;
        memcpy (z, str, s_len + 1);

        set_custom_quoting (NULL, q, q);
        /* Whether this actually triggers a SEGV depends on the
           implementation of memcmp: whether it compares only byte-at-
           a-time, and from left to right (no SEGV) or some other way.  */
        size_t n = quotearg_buffer (buf, sizeof buf, z, SIZE_MAX, NULL);
        ASSERT (n == s_len + 2 * q_len);
        ASSERT (memcmp (buf, q, sizeof buf) == 0);
        free (q);
      }
  }

  quotearg_free ();

  return 0;
}
Beispiel #8
0
int
main (int argc, char *argv[])
{
  int i;

  set_program_name (argv[0]);

  /* This program part is hard-wired to the C locale since it does not call
     setlocale.  */
  ASSERT (!isprint ('\033'));
  for (i = literal_quoting_style; i <= clocale_quoting_style; i++)
    {
      set_quoting_style (NULL, i);
      compare_strings (use_quotearg_buffer, &results_g[i].group1);
      compare_strings (use_quotearg, &results_g[i].group2);
      compare_strings (use_quotearg_colon, &results_g[i].group3);
    }

  set_quoting_style (NULL, literal_quoting_style);
  ASSERT (set_quoting_flags (NULL, QA_ELIDE_NULL_BYTES) == 0);
  compare_strings (use_quotearg_buffer, &flag_results[0].group1);
  compare_strings (use_quotearg, &flag_results[0].group2);
  compare_strings (use_quotearg_colon, &flag_results[0].group3);

  set_quoting_style (NULL, c_quoting_style);
  ASSERT (set_quoting_flags (NULL, QA_ELIDE_OUTER_QUOTES)
	  == QA_ELIDE_NULL_BYTES);
  compare_strings (use_quotearg_buffer, &flag_results[1].group1);
  compare_strings (use_quotearg, &flag_results[1].group2);
  compare_strings (use_quotearg_colon, &flag_results[1].group3);

  ASSERT (set_quoting_flags (NULL, QA_SPLIT_TRIGRAPHS)
	  == QA_ELIDE_OUTER_QUOTES);
  compare_strings (use_quotearg_buffer, &flag_results[2].group1);
  compare_strings (use_quotearg, &flag_results[2].group2);
  compare_strings (use_quotearg_colon, &flag_results[2].group3);

  ASSERT (set_quoting_flags (NULL, 0) == QA_SPLIT_TRIGRAPHS);

#if ENABLE_NLS
  /* Clean up environment.  */
  unsetenv ("LANGUAGE");
  unsetenv ("LC_ALL");
  unsetenv ("LC_MESSAGES");
  unsetenv ("LC_CTYPE");
  unsetenv ("LANG");
  unsetenv ("OUTPUT_CHARSET");

  /* This program part runs in a French UTF-8 locale.  It uses
     the test-quotearg.mo message catalog.  */
  {
    const char *locale_name = getenv ("LOCALE");

    if (locale_name != NULL && strcmp (locale_name, "none") != 0
	&& setenv ("LC_ALL", locale_name, 1) == 0
	&& setlocale (LC_ALL, "") != NULL)
      {
	textdomain ("test-quotearg");
	bindtextdomain ("test-quotearg", getenv ("LOCALEDIR"));

	set_quoting_style (NULL, locale_quoting_style);
	compare_strings (use_quotearg_buffer, &locale_results[0].group1);
	compare_strings (use_quotearg, &locale_results[0].group2);
	compare_strings (use_quotearg_colon, &locale_results[0].group3);

	set_quoting_style (NULL, clocale_quoting_style);
	compare_strings (use_quotearg_buffer, &locale_results[1].group1);
	compare_strings (use_quotearg, &locale_results[1].group2);
	compare_strings (use_quotearg_colon, &locale_results[1].group3);
      }
  }
#endif /* ENABLE_NLS */

  quotearg_free ();
  return 0;
}
Beispiel #9
0
int
main (int argc, char **argv)
{
    uint32_t c;
    char *config_file;
    bool custom_config;
    char *tmpdir;
    struct sigaction sigact;

    set_quoting_style(NULL, escape_quoting_style);

    if (setlocale(LC_ALL, "") == NULL)
        warn(_("%s: Cannot set locale: %s\n"), argv[0], errstr);
#ifdef ENABLE_NLS
    if (bindtextdomain(PACKAGE, LOCALEDIR) == NULL)
        warn(_("%s: Cannot bind message domain: %s\n"), argv[0], errstr);
    if (textdomain(PACKAGE) == NULL)
        warn(_("%s: Cannot set message domain: %s\n"), argv[0], errstr);
#endif

    custom_config = false;
    get_package_file("config", &config_file);

    while (true) {
        c = getopt_long(argc, argv, short_opts, long_opts, NULL);
        if (c == -1)
            break;

        switch (c) {
        case 'c': /* --config */
            custom_config = true;
            free(config_file);
            config_file = xstrdup(optarg);
            break;
        case 'n': /* --no-config */
            free(config_file);
            config_file = NULL;
            break;
        case HELP_OPT: /* --help */
            printf(_("Usage: %s [OPTION]...\n"), quotearg(argv[0]));
            puts(_("Start microdc, a command-line based Direct Connect client.\n"));
            printf(_("  -n, --no-config  do not read config file on startup\n"));
            printf(_("      --help       display this help and exit\n"));
            printf(_("      --version    output version information and exit\n"));
            printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
            exit(EXIT_SUCCESS);
        case VERSION_OPT: /* --version */
            version_etc(stdout, NULL, PACKAGE, VERSION, /*"Oskar Liljeblad",*/ "Vladimir Chugunov", NULL);
            exit(EXIT_SUCCESS);
        default:
            exit(EXIT_FAILURE);
        }
    }

    if (pipe(signal_pipe) < 0) {
        warn(_("Cannot create pipe pair - %s\n"), errstr);
        goto cleanup;
    }

    main_process_id = getpid();
    sigact.sa_handler = signal_received;
    if (sigemptyset(&sigact.sa_mask) < 0) {
        warn(_("Cannot empty signal set - %s\n"), errstr);
        goto cleanup;
    }
    sigact.sa_flags = SA_RESTART;
#ifdef HAVE_STRUCT_SIGACTION_SA_RESTORER
    sigact.sa_restorer = NULL;
#endif
    /* Note: every signal registered with a non-ignore action here must
     * also be registered in user.c, either with an action or as ignored.
     */
    if (sigaction(SIGINT,  &sigact, NULL) < 0 ||
            sigaction(SIGTERM, &sigact, NULL) < 0 ||
            sigaction(SIGUSR1, &sigact, NULL) < 0 ||
            sigaction(SIGCHLD, &sigact, NULL) < 0) {
        warn(_("Cannot register signal handler - %s\n"), errstr);
        goto cleanup;
    }
    sigact.sa_handler = SIG_IGN;
    if (sigaction(SIGPIPE, &sigact, NULL) < 0) {
        warn(_("Cannot register signal handler - %s\n"), errstr);
        goto cleanup;
    }

    FD_ZERO(&read_fds);
    FD_ZERO(&write_fds);
    FD_SET(signal_pipe[0], &read_fds);
    /*FD_SET(STDIN_FILENO, &read_fds);*/

    hub_recvq = byteq_new(128);
    hub_sendq = byteq_new(128);
    user_conns = hmap_new();
    hub_users = hmap_new();
    pending_userinfo = hmap_new();

    set_main_charset("");
    set_hub_charset("");
    set_fs_charset("");

    user_conn_unknown_free = ptrv_new();
    delete_files = ptrv_new();
    delete_dirs = ptrv_new();
    search_udpmsg_out = ptrv_new();
    our_searches = ptrv_new();
    search_recvq = byteq_new(8192); // same size as DC++
    my_nick = xstrdup(PACKAGE);
    my_description = xstrdup("");
    my_email = xstrdup("");
    my_speed = xstrdup("56Kbps");
    my_tag = xasprintf("%s V:%s", PACKAGE, VERSION);
    download_dir = xstrdup(".");
    tmpdir = tempdir();
    if (tmpdir == NULL) {
        warn(_("Cannot find directory for temporary files - %s\n"), errstr);
        goto cleanup;
    }
    {
        char *filename = xasprintf("%s.%d", PACKAGE, getpid());
        listing_dir = catfiles(tmpdir, filename);
        free(filename);
    }
    ptrv_append(delete_dirs, xstrdup(listing_dir));
    is_active = false;
    listen_port = 0;
    if (!local_file_list_update_init())
        goto cleanup;
    if (!set_active(false, listen_port))
        goto cleanup;
    if (!enable_search())
        goto cleanup;
    my_ul_slots = 3;

    if (!lookup_init())
        goto cleanup;
    if (!file_list_parse_init())
        goto cleanup;
    command_init();

    if (!local_file_list_init()) {
        goto cleanup;
    }

    if (config_file != NULL) {
        run_script(config_file, !custom_config);
        free(config_file);
        config_file = NULL;
    }

    screen_prepare();

    while (running) {
        fd_set res_read_fds;
        fd_set res_write_fds;
        int res;
        struct timeval tv;
        tv.tv_sec = 1;
        tv.tv_usec = 0;

        screen_redisplay_prompt();

        res_read_fds = read_fds;
        res_write_fds = write_fds;
        res = TEMP_FAILURE_RETRY(select(FD_SETSIZE, &res_read_fds, &res_write_fds, NULL, &tv));
        if (res < 0) {
            warn(_("Cannot select - %s\n"), errstr);
            break;
        }

        if (running && FD_ISSET(signal_pipe[0], &res_read_fds))
            read_signal_input();
        if (running && FD_ISSET(STDIN_FILENO, &res_read_fds))
            screen_read_input();
        if (running && listen_socket >= 0 && FD_ISSET(listen_socket, &res_read_fds))
            handle_listen_connection();
        if (running && hub_socket >= 0 && FD_ISSET(hub_socket, &res_read_fds))
            hub_input_available();
        if (running && hub_socket >= 0 && FD_ISSET(hub_socket, &res_write_fds))
            hub_now_writable();
        if (running)
            check_hub_activity();
        if (running && search_socket >= 0 && FD_ISSET(search_socket, &res_read_fds))
            search_input_available();
        if (running && search_socket >= 0 && FD_ISSET(search_socket, &res_write_fds))
            search_now_writable();
        if (running && FD_ISSET(lookup_request_mq->fd, &res_write_fds))
            lookup_request_fd_writable();
        if (running && FD_ISSET(lookup_result_mq->fd, &res_read_fds))
            lookup_result_fd_readable();
        if (running && FD_ISSET(parse_request_mq->fd, &res_write_fds))
            parse_request_fd_writable();
        if (running && FD_ISSET(parse_result_mq->fd, &res_read_fds))
            parse_result_fd_readable();
        if (running && FD_ISSET(update_request_mq->fd, &res_write_fds))
            update_request_fd_writable();
        if (running && FD_ISSET(update_result_mq->fd, &res_read_fds))
            update_result_fd_readable();

        if (running) {
            HMapIterator it;

            hmap_iterator(user_conns, &it);
            while (running && it.has_next(&it)) {
                DCUserConn *uc = (DCUserConn*) it.next(&it);
                if (uc->put_mq != NULL && FD_ISSET(uc->put_mq->fd, &res_write_fds))
                    user_request_fd_writable(uc);
                if (uc->get_mq != NULL && FD_ISSET(uc->get_mq->fd, &res_read_fds))
                    user_result_fd_readable(uc);
            }
        }
    }

cleanup:

    hub_disconnect();
    screen_finish();
    command_finish();
    local_file_list_update_finish();
    file_list_parse_finish();
    lookup_finish();

    byteq_free(hub_recvq);
    byteq_free(hub_sendq);
    hmap_free(hub_users); /* Emptied by hub_disconnect */
    hmap_free(pending_userinfo); /* Emptied by hub_disconnect */

    byteq_free(search_recvq);

    ptrv_foreach(user_conn_unknown_free, free);
    ptrv_free(user_conn_unknown_free);

    ptrv_foreach(search_udpmsg_out, free);
    ptrv_free(search_udpmsg_out);

    ptrv_foreach(our_searches, (PtrVForeachCallback) free_search_request);
    ptrv_free(our_searches);

    hmap_foreach_value(user_conns, (void (*) (void*)) user_conn_cancel);
    /* XXX: follow up and wait for user connections to die? */
    hmap_free(user_conns);

    if (our_filelist != NULL)
        filelist_free(our_filelist);

    set_main_charset(NULL);
    set_hub_charset(NULL);
    set_fs_charset(NULL);

    free(hub_name);
    free(my_nick);
    free(my_description);
    free(my_email);
    free(my_speed);
    free(my_tag);
    free(download_dir);
    free(listing_dir);

    if (delete_files != NULL) {
        for (c = 0; c < delete_files->cur; c++) {
            char *filename = (char*) delete_files->buf[c];
            struct stat st;

            if (stat(filename, &st) < 0) {
                if (errno != ENOENT)
                    warn(_("%s: Cannot get file status - %s\n"), quotearg(filename), errstr);
                free(filename);
                continue;
            }
            if (unlink(filename) < 0)
                warn(_("%s: Cannot remove file - %s\n"), quotearg(filename), errstr);
            free(filename);
        }
        ptrv_free(delete_files);
    }

    if (delete_dirs != NULL) {
        for (c = 0; c < delete_dirs->cur; c++) {
            char *filename = (char*) delete_dirs->buf[c];
            struct stat st;

            if (stat(filename, &st) < 0) {
                if (errno != ENOENT)
                    warn(_("%s: Cannot get file status - %s\n"), quotearg(filename), errstr);
                free(filename);
                continue;
            }
            if (rmdir(filename) < 0)
                warn(_("%s: Cannot remove file - %s\n"), quotearg(filename), errstr);
            free(filename);
        }
        ptrv_free(delete_dirs);
    }

    if (search_socket >= 0 && close(search_socket) < 0)
        warn(_("Cannot close search results socket - %s\n"), errstr);
    if (listen_socket >= 0 && close(listen_socket) < 0)
        warn(_("Cannot close user connections socket - %s\n"), errstr);
    if (signal_pipe[0] >= 0 && close(signal_pipe[0]) < 0)
        warn(_("Cannot close signal pipe - %s\n"), errstr);
    if (signal_pipe[1] >= 0 && close(signal_pipe[1]) < 0)
        warn(_("Cannot close signal pipe - %s\n"), errstr);

    free(config_file);

    exit(EXIT_SUCCESS);
}