mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-27 20:25:12 +00:00
Hack around xdm's dumb assumption that the login shell is POSIX compliant so we no longer kill OpenSUSE
https://github.com/fish-shell/fish-shell/issues/367 Also fix some formatting
This commit is contained in:
parent
77f1b1f0fe
commit
edb973fadc
8 changed files with 174 additions and 72 deletions
113
expand.cpp
113
expand.cpp
|
@ -1785,3 +1785,116 @@ bool expand_one(wcstring &string, expand_flags_t flags)
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
https://github.com/fish-shell/fish-shell/issues/367
|
||||
|
||||
With them the Seed of Wisdom did I sow,
|
||||
And with my own hand labour'd it to grow:
|
||||
And this was all the Harvest that I reap'd---
|
||||
"I came like Water, and like Wind I go."
|
||||
|
||||
*/
|
||||
|
||||
static std::string escape_single_quoted_hack_hack_hack_hack(const char *str)
|
||||
{
|
||||
std::string result;
|
||||
size_t len = strlen(str);
|
||||
result.reserve(len + 2);
|
||||
result.push_back('\'');
|
||||
for (size_t i=0; i < len; i++)
|
||||
{
|
||||
char c = str[i];
|
||||
// Escape backslashes and single quotes only
|
||||
if (c == '\\' || c == '\'')
|
||||
result.push_back('\\');
|
||||
result.push_back(c);
|
||||
}
|
||||
result.push_back('\'');
|
||||
return result;
|
||||
}
|
||||
|
||||
bool fish_xdm_login_hack_hack_hack_hack(std::vector<std::string> *cmds, int argc, const char * const *argv)
|
||||
{
|
||||
bool result = false;
|
||||
if (cmds && cmds->size() == 1)
|
||||
{
|
||||
const std::string &cmd = cmds->at(0);
|
||||
if (cmd == "exec \"${@}\"" || cmd == "exec \"$@\"")
|
||||
{
|
||||
/* We're going to construct a new command that starts with exec, and then has the remaining arguments escaped */
|
||||
std::string new_cmd = "exec";
|
||||
for (int i=1; i < argc; i++)
|
||||
{
|
||||
const char *arg = argv[i];
|
||||
if (arg)
|
||||
{
|
||||
new_cmd.push_back(' ');
|
||||
new_cmd.append(escape_single_quoted_hack_hack_hack_hack(arg));
|
||||
}
|
||||
}
|
||||
|
||||
cmds->at(0) = new_cmd;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool fish_openSUSE_dbus_hack_hack_hack_hack(std::vector<completion_t> *args)
|
||||
{
|
||||
static signed char isSUSE = -1;
|
||||
if (isSUSE == 0)
|
||||
return false;
|
||||
|
||||
bool result = false;
|
||||
if (args && ! args->empty())
|
||||
{
|
||||
const wcstring &cmd = args->at(0).completion;
|
||||
if (cmd.find(L"DBUS_SESSION_BUS_") != wcstring::npos)
|
||||
{
|
||||
/* See if we are SUSE */
|
||||
if (isSUSE < 0)
|
||||
{
|
||||
struct stat buf = {};
|
||||
isSUSE = (0 == stat("/etc/SuSE-release", &buf));
|
||||
}
|
||||
|
||||
if (isSUSE)
|
||||
{
|
||||
/* Look for an equal sign */
|
||||
size_t where = cmd.find(L'=');
|
||||
if (where != wcstring::npos)
|
||||
{
|
||||
/* Oh my. It's presumably of the form foo=bar; find the = and split */
|
||||
const wcstring key = wcstring(cmd, 0, where);
|
||||
|
||||
/* Trim whitespace and semicolon */
|
||||
wcstring val = wcstring(cmd, where+1);
|
||||
size_t last_good = val.find_last_not_of(L"\n ;");
|
||||
if (last_good != wcstring::npos)
|
||||
val.resize(last_good + 1);
|
||||
|
||||
args->clear();
|
||||
args->push_back(completion_t(L"set"));
|
||||
if (key == L"DBUS_SESSION_BUS_ADDRESS")
|
||||
args->push_back(completion_t(L"-x"));
|
||||
args->push_back(completion_t(key));
|
||||
args->push_back(completion_t(val));
|
||||
result = true;
|
||||
}
|
||||
else if (string_prefixes_string(L"export DBUS_SESSION_BUS_ADDRESS;", cmd))
|
||||
{
|
||||
/* Nothing, we already exported it */
|
||||
args->clear();
|
||||
args->push_back(completion_t(L"echo"));
|
||||
args->push_back(completion_t(L"-n"));
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
7
expand.h
7
expand.h
|
@ -200,4 +200,11 @@ void expand_variable_error(parser_t &parser, const wchar_t *token, size_t token_
|
|||
*/
|
||||
std::vector<wcstring> expand_get_all_process_names(void);
|
||||
|
||||
/* Terrible hacks */
|
||||
bool fish_xdm_login_hack_hack_hack_hack(std::vector<std::string> *cmds, int argc, const char * const *argv);
|
||||
bool fish_openSUSE_dbus_hack_hack_hack_hack(std::vector<completion_t> *args);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
72
fish.cpp
72
fish.cpp
|
@ -245,51 +245,26 @@ static int read_init(const struct config_paths_t &paths)
|
|||
Parse the argument list, return the index of the first non-switch
|
||||
arguments.
|
||||
*/
|
||||
static int fish_parse_opt(int argc, char **argv, const char **cmd_ptr)
|
||||
static int fish_parse_opt(int argc, char **argv, std::vector<std::string> *out_cmds)
|
||||
{
|
||||
int my_optind;
|
||||
int force_interactive=0;
|
||||
bool has_cmd = false;
|
||||
|
||||
while (1)
|
||||
{
|
||||
static struct option
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
"command", required_argument, 0, 'c'
|
||||
}
|
||||
,
|
||||
{
|
||||
"debug-level", required_argument, 0, 'd'
|
||||
}
|
||||
,
|
||||
{
|
||||
"interactive", no_argument, 0, 'i'
|
||||
}
|
||||
,
|
||||
{
|
||||
"login", no_argument, 0, 'l'
|
||||
}
|
||||
,
|
||||
{
|
||||
"no-execute", no_argument, 0, 'n'
|
||||
}
|
||||
,
|
||||
{
|
||||
"profile", required_argument, 0, 'p'
|
||||
}
|
||||
,
|
||||
{
|
||||
"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
"version", no_argument, 0, 'v'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
{ "command", required_argument, 0, 'c' },
|
||||
{ "debug-level", required_argument, 0, 'd' },
|
||||
{ "interactive", no_argument, 0, 'i' } ,
|
||||
{ "login", no_argument, 0, 'l' },
|
||||
{ "no-execute", no_argument, 0, 'n' },
|
||||
{ "profile", required_argument, 0, 'p' },
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "version", no_argument, 0, 'v' },
|
||||
{ 0, 0, 0, 0 }
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -313,7 +288,8 @@ static int fish_parse_opt(int argc, char **argv, const char **cmd_ptr)
|
|||
|
||||
case 'c':
|
||||
{
|
||||
*cmd_ptr = optarg;
|
||||
out_cmds->push_back(optarg ? optarg : "");
|
||||
has_cmd = true;
|
||||
is_interactive_session = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -340,7 +316,8 @@ static int fish_parse_opt(int argc, char **argv, const char **cmd_ptr)
|
|||
|
||||
case 'h':
|
||||
{
|
||||
*cmd_ptr = "__fish_print_help fish";
|
||||
out_cmds->push_back("__fish_print_help fish");
|
||||
has_cmd = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -393,7 +370,7 @@ static int fish_parse_opt(int argc, char **argv, const char **cmd_ptr)
|
|||
We are an interactive session if we have not been given an
|
||||
explicit command to execute, _and_ stdin is a tty.
|
||||
*/
|
||||
is_interactive_session &= (*cmd_ptr == 0);
|
||||
is_interactive_session &= has_cmd;
|
||||
is_interactive_session &= (my_optind == argc);
|
||||
is_interactive_session &= isatty(STDIN_FILENO);
|
||||
|
||||
|
@ -439,7 +416,6 @@ extern int g_fork_count;
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
int res=1;
|
||||
const char *cmd=0;
|
||||
int my_optind=0;
|
||||
|
||||
set_main_thread();
|
||||
|
@ -453,7 +429,8 @@ int main(int argc, char **argv)
|
|||
//struct stat tmp;
|
||||
//stat("----------FISH_HIT_MAIN----------", &tmp);
|
||||
|
||||
my_optind = fish_parse_opt(argc, argv, &cmd);
|
||||
std::vector<std::string> cmds;
|
||||
my_optind = fish_parse_opt(argc, argv, &cmds);
|
||||
|
||||
/*
|
||||
No-exec is prohibited when in interactive mode
|
||||
|
@ -483,10 +460,19 @@ int main(int argc, char **argv)
|
|||
const io_chain_t empty_ios;
|
||||
if (read_init(paths))
|
||||
{
|
||||
if (cmd != NULL)
|
||||
/* Run the commands specified as arguments, if any */
|
||||
if (! cmds.empty())
|
||||
{
|
||||
const wcstring cmd_wcs = str2wcstring(cmd);
|
||||
/* Do something nasty to support OpenSUSE assuming we're bash. This may modify cmds. */
|
||||
if (is_login)
|
||||
{
|
||||
fish_xdm_login_hack_hack_hack_hack(&cmds, argc - my_optind, argv + my_optind);
|
||||
}
|
||||
for (size_t i=0; i < cmds.size(); i++)
|
||||
{
|
||||
const wcstring cmd_wcs = str2wcstring(cmds.at(i));
|
||||
res = parser.eval(cmd_wcs, empty_ios, TOP);
|
||||
}
|
||||
reader_exit(0, 0);
|
||||
}
|
||||
else
|
||||
|
|
13
parser.cpp
13
parser.cpp
|
@ -2071,6 +2071,18 @@ int parser_t::parse_job(process_t *p,
|
|||
}
|
||||
}
|
||||
|
||||
// Disabled pending discussion in https://github.com/fish-shell/fish-shell/issues/367
|
||||
#if 0
|
||||
if (! has_command && ! use_implicit_cd)
|
||||
{
|
||||
if (fish_openSUSE_dbus_hack_hack_hack_hack(&args))
|
||||
{
|
||||
has_command = true;
|
||||
p->type = INTERNAL_BUILTIN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check if the specified command exists */
|
||||
if (! has_command && ! use_implicit_cd)
|
||||
{
|
||||
|
@ -3858,3 +3870,4 @@ breakpoint_block_t::breakpoint_block_t() :
|
|||
block_t(BREAKPOINT)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
17
util.h
17
util.h
|
@ -1,11 +1,5 @@
|
|||
/** \file util.h
|
||||
Generic utilities library.
|
||||
|
||||
All containers in this library except strinb_buffer_t are written
|
||||
so that they don't allocate any memory until the first element is
|
||||
inserted into them. That way it is known to be very cheap to
|
||||
initialize various containers at startup, supporting the fish
|
||||
notion of doing as much lazy initalization as possible.
|
||||
*/
|
||||
|
||||
#ifndef FISH_UTIL_H
|
||||
|
@ -15,17 +9,6 @@
|
|||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
Buffer for concatenating arbitrary data.
|
||||
*/
|
||||
typedef struct buffer
|
||||
{
|
||||
char *buff; /**<data buffer*/
|
||||
size_t length; /**< Size of buffer */
|
||||
size_t used; /**< Size of data in buffer */
|
||||
}
|
||||
buffer_t;
|
||||
|
||||
/**
|
||||
Returns the larger of two ints
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue