mirror of
https://github.com/fish-shell/fish-shell
synced 2024-11-10 07:04:29 +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
|
@ -1970,11 +1970,11 @@ void complete(const wcstring &cmd, std::vector<completion_t> &comps, complete_ty
|
|||
See https://github.com/fish-shell/fish-shell/issues/378 */
|
||||
if (commands_to_load != NULL && completer.has_commands_to_load())
|
||||
do_file = false;
|
||||
|
||||
|
||||
/* And if we're autosuggesting, and the token is empty, don't do file suggestions */
|
||||
if (type == COMPLETE_AUTOSUGGEST && current_token_unescape.empty())
|
||||
do_file = false;
|
||||
|
||||
|
||||
/*
|
||||
This function wants the unescaped string
|
||||
*/
|
||||
|
|
|
@ -113,14 +113,14 @@ static int try_get_socket_once(void)
|
|||
uname = pw->pw_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string name;
|
||||
name.reserve(strlen(dir) + uname.size() + strlen(SOCK_FILENAME) + 2);
|
||||
name.append(dir);
|
||||
name.append("/");
|
||||
name.append(SOCK_FILENAME);
|
||||
name.append(uname);
|
||||
|
||||
|
||||
free(dir);
|
||||
|
||||
debug(3, L"Connect to socket %s at fd %2", name.c_str(), s);
|
||||
|
@ -145,7 +145,7 @@ static int try_get_socket_once(void)
|
|||
}
|
||||
|
||||
debug(3, L"Connected to fd %d", s);
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -155,16 +155,16 @@ static int try_get_socket_once(void)
|
|||
static int get_socket(void)
|
||||
{
|
||||
get_socket_count++;
|
||||
|
||||
|
||||
int s = try_get_socket_once();
|
||||
if (s < 0)
|
||||
{
|
||||
if (start_fishd)
|
||||
{
|
||||
debug(2, L"Could not connect to socket %d, starting fishd", s);
|
||||
|
||||
|
||||
start_fishd();
|
||||
|
||||
|
||||
for (size_t i=0; s < 0 && i < DEFAULT_RETRY_COUNT; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
|
@ -176,13 +176,13 @@ static int get_socket(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (s < 0)
|
||||
{
|
||||
debug(1, L"Could not connect to universal variable server, already tried manual restart (or no command supplied). You will not be able to share variable values between fish sessions. Is fish properly installed?");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
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
|
||||
|
||||
|
||||
|
|
74
fish.cpp
74
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);
|
||||
res = parser.eval(cmd_wcs, empty_ios, TOP);
|
||||
/* 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
|
||||
*/
|
||||
|
|
|
@ -330,7 +330,7 @@ wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path)
|
|||
|
||||
if (!narrow_res)
|
||||
return 0;
|
||||
|
||||
|
||||
const wcstring wide_res = str2wcstring(narrow_res);
|
||||
if (resolved_path)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue