/* * SPDX-FileCopyrightText: 2003-2026 Sébastien Helleu * * SPDX-License-Identifier: GPL-3.0-or-later * * This file is part of WeeChat, the extensible chat client. * * WeeChat is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * WeeChat is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with WeeChat. If not, see . */ /* Function for command-line arguments */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "weechat.h" #include "core-debug.h" #include "core-list.h" #include "core-string.h" #include "core-utf8.h" #include "core-version.h" #include "../gui/gui-color.h" #include "../plugins/plugin.h" /* some command line options */ #define OPTION_DOCGEN 1000 #define OPTION_NO_DLCLOSE 1001 #define OPTION_NO_GNUTLS 1002 #define OPTION_NO_GCRYPT 1003 char *weechat_args_common[][2] = { { "-a, --no-connect", /* TRANSLATORS: command line option "-a", "--no-connect" */ N_("disable auto-connect to servers at startup"), }, { "-c, --colors", /* TRANSLATORS: command line option "-c", "--colors" */ N_("display default colors in terminal and exit"), }, { /* TRANSLATORS: only "" may be translated */ N_("-d, --dir "), /* TRANSLATORS: command line option "-d", "--dir " */ N_("force a single WeeChat home directory or 5 different directories " "separated by colons (in this order: config, data, state, cache, runtime) " "(environment variable WEECHAT_HOME is read if this option is not given)"), }, { "-t, --temp-dir", /* TRANSLATORS: command line option "-t", "--temp-dir" */ N_("create a temporary WeeChat home directory and delete it on exit " "(incompatible with option \"-d\")"), }, { "-h, --help", /* TRANSLATORS: command line option "-h", "--help" */ N_("display this help and exit"), }, { "-i, --build-info", /* TRANSLATORS: command line option "-i", "--build-info" */ N_("display build information and exit"), }, { "-l, --license", /* TRANSLATORS: command line option "-l", "--license" */ N_("display WeeChat license and exit"), }, { "-p, --no-plugin", /* TRANSLATORS: command line option "-p", "--no-plugin" */ N_("don't load any plugin at startup"), }, { /* TRANSLATORS: only "" may be translated */ N_("-P, --plugins "), /* TRANSLATORS: command line option "-P", "--plugins " */ N_("load only these plugins at startup (see /help weechat.plugin.autoload)"), }, { /* TRANSLATORS: only "" may be translated (please keep it short) */ N_("-r, --run-command "), /* TRANSLATORS: command line option "-r", "--run-command " */ N_("run command(s) after startup; many commands can be separated " "by semicolons and are evaluated, this option can be given multiple times"), }, { "-s, --no-script", /* TRANSLATORS: command line option "-s", "--no-script" */ N_("don't load any script at startup"), }, { "--upgrade", /* TRANSLATORS: command line option "--upgrade" */ N_("upgrade WeeChat using session files (see /help upgrade in WeeChat)"), }, { "-v, --version", /* TRANSLATORS: command line option "-v", "--version" */ N_("display WeeChat version and exit"), }, { /* TRANSLATORS: command line option: "plugin" and "option" may be translated */ N_("plugin:option"), /* TRANSLATORS: command line option "plugin:option" */ N_("option for plugin (see man weechat)"), }, { NULL, NULL }, }; char *weechat_args_headless[][2] = { { /* TRANSLATORS: only "" may be translated */ N_("--doc-gen "), /* TRANSLATORS: command line option "--doc-gen " */ N_("generate files to build documentation and exit"), }, { "--daemon", /* TRANSLATORS: command line option "--daemon" */ N_("run WeeChat as a daemon (fork, new process group, file descriptors closed); " "by default in headless mode WeeChat is blocking and does not run in background"), }, { "--stdout", /* TRANSLATORS: command line option "--stdout" */ N_("display log messages on standard output instead of writing them in log file " "(option ignored if option \"--daemon\" is given)"), }, { NULL, NULL }, }; char *weechat_args_debug[][2] = { { "--no-dlclose", /* TRANSLATORS: command line option "--no-dlclose" */ N_("do not call function dlclose after plugins are unloaded"), }, { "--no-gnutls", /* TRANSLATORS: command line option "--no-gnutls" */ N_("disable init/deinit of gnutls"), }, { "--no-gcrypt", /* TRANSLATORS: command line option "--no-gcrypt" */ N_("disable init/deinit of gcrypt"), }, { NULL, NULL }, }; /* * Display WeeChat copyright on standard output. */ void args_display_copyright (void) { string_fprintf (stdout, "\n"); string_fprintf ( stdout, /* TRANSLATORS: "%s %s" after "compiled on" is date and time */ _("WeeChat %s Copyright %s, compiled on %s %s\n" "Developed by %s <%s> " "- %s"), version_get_version_with_git (), WEECHAT_COPYRIGHT_DATE, version_get_compilation_date (), version_get_compilation_time (), WEECHAT_AUTHOR_NAME, WEECHAT_AUTHOR_EMAIL, WEECHAT_WEBSITE); string_fprintf (stdout, "\n"); } void args_display_list_args (char *args[][2]) { int i, j, length, length_fill, max_length_screen; const char *ptr_text; max_length_screen = 0; for (i = 0; args[i][0]; i++) { length = utf8_strlen_screen (_(args[i][0])); if (length > max_length_screen) max_length_screen = length; } for (i = 0; args[i][0]; i++) { ptr_text = _(args[i][0]); length = utf8_strlen_screen (ptr_text); length_fill = max_length_screen - length; string_fprintf (stdout, " %s", ptr_text); for (j = 0; j < length_fill; j++) { string_fprintf (stdout, " "); } string_fprintf (stdout, " %s\n", _(args[i][1])); } } /* * Display WeeChat help on standard output. */ void args_display_help (void) { args_display_copyright (); string_fprintf (stdout, "\n"); string_fprintf (stdout, "%s %s %s\n\n", _("Usage:"), weechat_argv0, _("[option...] [plugin:option...]")); args_display_list_args (weechat_args_common); string_fprintf (stdout, "\n"); /* extra options in headless mode */ if (weechat_headless) { string_fprintf (stdout, "%s\n", _("Extra options in headless mode:")); args_display_list_args (weechat_args_headless); string_fprintf (stdout, "\n"); } /* debug options */ string_fprintf (stdout, "%s\n", _("Debug options (for tools like valgrind, " "DO NOT USE IN PRODUCTION):")); args_display_list_args (weechat_args_debug); string_fprintf (stdout, "\n"); } /* * Parse command line arguments. * * Arguments argc and argv come from main() function. */ void args_parse (int argc, char *argv[]) { int opt; struct option long_options[] = { /* standard options */ { "no-connect", no_argument, NULL, 'a' }, { "colors", no_argument, NULL, 'c' }, { "dir", required_argument, NULL, 'd' }, { "temp-dir", no_argument, NULL, 't' }, { "help", no_argument, NULL, 'h' }, { "build-info", no_argument, NULL, 'i' }, { "license", no_argument, NULL, 'l' }, { "no-plugin", no_argument, NULL, 'p' }, { "plugins", required_argument, NULL, 'P' }, { "run-command", required_argument, NULL, 'r' }, { "no-script", no_argument, NULL, 's' }, { "upgrade", no_argument, NULL, 'u' }, { "doc-gen", required_argument, NULL, OPTION_DOCGEN }, { "version", no_argument, NULL, 'v' }, /* debug options */ { "no-dlclose", no_argument, NULL, OPTION_NO_DLCLOSE }, { "no-gnutls", no_argument, NULL, OPTION_NO_GNUTLS }, { "no-gcrypt", no_argument, NULL, OPTION_NO_GCRYPT }, { NULL, 0, NULL, 0 }, }; weechat_argv0 = (argv[0]) ? strdup (argv[0]) : NULL; weechat_upgrading = 0; weechat_home_force = NULL; weechat_home_temp = 0; weechat_home_delete_on_exit = 0; weechat_server_cmd_line = 0; weechat_force_plugin_autoload = NULL; weechat_doc_gen = 0; weechat_plugin_no_dlclose = 0; optind = 0; opterr = 0; while ((opt = getopt_long (argc, argv, ":acd:thilpP:r:sv", long_options, NULL)) != -1) { switch (opt) { case 'a': /* -a / --no-connect */ /* option ignored, it will be used by plugins/scripts */ break; case 'c': /* -c / --colors */ gui_color_display_terminal_colors (); weechat_shutdown (EXIT_SUCCESS, 0); break; case 'd': /* -d / --dir */ weechat_home_temp = 0; free (weechat_home_force); weechat_home_force = strdup (optarg); break; case 't': /* -t / --temp-dir */ weechat_home_temp = 1; if (weechat_home_force) { free (weechat_home_force); weechat_home_force = NULL; } break; case 'h': /* -h / --help */ args_display_help (); weechat_shutdown (EXIT_SUCCESS, 0); break; case 'i': /* -i / --build-info */ debug_build_info (); weechat_shutdown (EXIT_SUCCESS, 0); break; case 'l': /* -l / --license */ args_display_copyright (); string_fprintf (stdout, "\n"); string_fprintf (stdout, "%s%s", WEECHAT_LICENSE_TEXT); weechat_shutdown (EXIT_SUCCESS, 0); break; case 'p': /* -p / --no-plugin */ free (weechat_force_plugin_autoload); weechat_force_plugin_autoload = strdup ("!*"); break; case 'P': /* -P / --plugins */ free (weechat_force_plugin_autoload); weechat_force_plugin_autoload = strdup (optarg); break; case 'r': /* -r / --run-command */ if (!weechat_startup_commands) weechat_startup_commands = weelist_new (); weelist_add (weechat_startup_commands, optarg, WEECHAT_LIST_POS_END, NULL); break; case 's': /* -s / --no-script */ /* option ignored, it will be used by the scripting plugins */ break; case 'u': /* --upgrade */ weechat_upgrading = 1; break; case OPTION_DOCGEN: /* --doc-gen */ if (weechat_headless) { weechat_doc_gen = 1; weechat_doc_gen_path = strdup (optarg); } break; case 'v': /* -v / --version */ string_fprintf (stdout, version_get_version ()); fprintf (stdout, "\n"); weechat_shutdown (EXIT_SUCCESS, 0); break; case OPTION_NO_DLCLOSE: /* --no-dlclose */ /* * Valgrind works better when dlclose() is not done after * plugins are unloaded, it can display stack for plugins,* * otherwise you'll see "???" in stack for functions of * unloaded plugins. * This option disables the call to dlclose(), * it must NOT be used for other purposes! */ weechat_plugin_no_dlclose = 1; break; case OPTION_NO_GNUTLS: /* --no-gnutls */ /* * Electric-fence is not working fine when gnutls loads * certificates and Valgrind reports many memory errors with * gnutls. * This option disables the init/deinit of gnutls, * it must NOT be used for other purposes! */ weechat_no_gnutls = 1; break; case OPTION_NO_GCRYPT: /* --no-gcrypt */ /* * Valgrind reports many memory errors with gcrypt. * This option disables the init/deinit of gcrypt, * it must NOT be used for other purposes! */ weechat_no_gcrypt = 1; break; case ':': string_fprintf (stderr, _("Error: missing argument for \"%s\" option\n"), argv[optind - 1]); weechat_shutdown (EXIT_FAILURE, 0); break; case '?': /* ignore any unknown option; plugins can use them */ break; default: /* ignore any other error */ break; } } }