diff --git a/Makefile.in b/Makefile.in index c132b5f90..63c94993e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -100,7 +100,8 @@ HAVE_DOXYGEN=@HAVE_DOXYGEN@ # FISH_OBJS := obj/autoload.o obj/builtin.o obj/builtin_bind.o obj/builtin_block.o \ obj/builtin_commandline.o obj/builtin_emit.o obj/builtin_functions.o \ - obj/builtin_bg.o obj/builtin_fg.o obj/builtin_return.o \ + obj/builtin_bg.o obj/builtin_fg.o obj/builtin_return.o obj/builtin_exit.o \ + obj/builtin_realpath.o \ obj/builtin_history.o obj/builtin_status.o obj/builtin_read.o obj/builtin_pwd.o \ obj/builtin_source.o obj/builtin_random.o obj/builtin_echo.o \ obj/builtin_cd.o obj/builtin_disown.o obj/builtin_function.o \ diff --git a/src/builtin.cpp b/src/builtin.cpp index c11783811..9caaeab63 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -40,6 +40,7 @@ #include "builtin_disown.h" #include "builtin_echo.h" #include "builtin_emit.h" +#include "builtin_exit.h" #include "builtin_fg.h" #include "builtin_functions.h" #include "builtin_history.h" @@ -48,6 +49,7 @@ #include "builtin_pwd.h" #include "builtin_random.h" #include "builtin_read.h" +#include "builtin_realpath.h" #include "builtin_return.h" #include "builtin_set.h" #include "builtin_set_color.h" @@ -117,7 +119,7 @@ int parse_cmd_opts_help_only(struct cmd_opts_help_only *opts, int *optind, int a switch (opt) { //!OCLINT(too few branches) case 'h': { opts->print_help = true; - return STATUS_CMD_OK; + break; } case '?': { builtin_unknown_option(parser, streams, cmd, argv[w.woptind - 1]); @@ -309,32 +311,6 @@ static int builtin_generic(parser_t &parser, io_streams_t &streams, wchar_t **ar return STATUS_CMD_ERROR; } -/// The exit builtin. Calls reader_exit to exit and returns the value specified. -static int builtin_exit(parser_t &parser, io_streams_t &streams, wchar_t **argv) { - int argc = builtin_count_args(argv); - - if (argc > 2) { - streams.err.append_format(_(L"%ls: Too many arguments\n"), argv[0]); - builtin_print_help(parser, streams, argv[0], streams.err); - return STATUS_INVALID_ARGS; - } - - long ec; - if (argc == 1) { - ec = proc_get_last_status(); - } else { - ec = fish_wcstol(argv[1]); - if (errno) { - streams.err.append_format(_(L"%ls: Argument '%ls' must be an integer\n"), argv[0], - argv[1]); - builtin_print_help(parser, streams, argv[0], streams.err); - return STATUS_INVALID_ARGS; - } - } - reader_exit(1, 0); - return (int)ec; -} - /// Implementation of the builtin count command, used to count the number of arguments sent to it. static int builtin_count(parser_t &parser, io_streams_t &streams, wchar_t **argv) { UNUSED(parser); @@ -418,32 +394,6 @@ int builtin_false(parser_t &parser, io_streams_t &streams, wchar_t **argv) { return STATUS_CMD_ERROR; } -/// An implementation of the external realpath command that doesn't support any options. It's meant -/// to be used only by scripts which need to be portable. In general scripts shouldn't invoke this -/// directly. They should just use `realpath` which will fallback to this builtin if an external -/// command cannot be found. This behaves like the external `realpath --canonicalize-existing`; -/// that is, it requires all path components, including the final, to exist. -int builtin_realpath(parser_t &parser, io_streams_t &streams, wchar_t **argv) { - int argc = builtin_count_args(argv); - - if (argc != 2) { - builtin_print_help(parser, streams, argv[0], streams.out); - return STATUS_INVALID_ARGS; - } - - wchar_t *real_path = wrealpath(argv[1], NULL); - if (real_path) { - streams.out.append(real_path); - free((void *)real_path); - } else { - // We don't actually know why it failed. We should check errno. - streams.err.append_format(_(L"%ls: Invalid path: %ls\n"), argv[0], argv[1]); - return STATUS_CMD_ERROR; - } - streams.out.append(L"\n"); - return STATUS_CMD_OK; -} - // END OF BUILTIN COMMANDS // Below are functions for handling the builtin commands. // THESE MUST BE SORTED BY NAME! Completion lookup uses binary search. diff --git a/src/builtin_realpath.cpp b/src/builtin_realpath.cpp new file mode 100644 index 000000000..34e6dc521 --- /dev/null +++ b/src/builtin_realpath.cpp @@ -0,0 +1,52 @@ +// Implementation of the realpath builtin. +#include "config.h" // IWYU pragma: keep + +#include +#include +#include + +#include "builtin.h" +#include "builtin_realpath.h" +#include "common.h" +#include "fallback.h" // IWYU pragma: keep +#include "io.h" +#include "wutil.h" // IWYU pragma: keep + +/// An implementation of the external realpath command that doesn't support any options. It's meant +/// to be used only by scripts which need to be portable. In general scripts shouldn't invoke this +/// directly. They should just use `realpath` which will fallback to this builtin if an external +/// command cannot be found. This behaves like the external `realpath --canonicalize-existing`; +/// that is, it requires all path components, including the final, to exist. +int builtin_realpath(parser_t &parser, io_streams_t &streams, wchar_t **argv) { + const wchar_t *cmd = argv[0]; + int argc = builtin_count_args(argv); + struct cmd_opts_help_only opts; + + int optind; + int retval = parse_cmd_opts_help_only(&opts, &optind, argc, argv, parser, streams); + if (retval != STATUS_CMD_OK) return retval; + + if (opts.print_help) { + builtin_print_help(parser, streams, cmd, streams.out); + return STATUS_CMD_OK; + } + + if (optind + 1 != argc) { + fwprintf(stderr, L"WTF argc %d optind %d\n", argc, optind); + streams.err.append_format(BUILTIN_ERR_ARG_COUNT1, cmd, 1, argc - optind); + builtin_print_help(parser, streams, cmd, streams.out); + return STATUS_INVALID_ARGS; + } + + wchar_t *real_path = wrealpath(argv[optind], NULL); + if (real_path) { + streams.out.append(real_path); + free((void *)real_path); + } else { + // We don't actually know why it failed. We should check errno. + streams.err.append_format(_(L"%ls: Invalid path: %ls\n"), cmd, argv[optind]); + return STATUS_CMD_ERROR; + } + streams.out.append(L"\n"); + return STATUS_CMD_OK; +} diff --git a/src/builtin_realpath.h b/src/builtin_realpath.h new file mode 100644 index 000000000..1fa7d16ad --- /dev/null +++ b/src/builtin_realpath.h @@ -0,0 +1,9 @@ +// Prototypes for executing builtin_realpath function. +#ifndef FISH_BUILTIN_REALPATH_H +#define FISH_BUILTIN_REALPATH_H + +class parser_t; +struct io_streams_t; + +int builtin_realpath(parser_t &parser, io_streams_t &streams, wchar_t **argv); +#endif