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 */ }
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); } }
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 ("e_quoting_options, "'", "'"); else set_quoting_style ("e_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; }
/* 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); }
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; }
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; }
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); }