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:
ridiculousfish 2013-01-04 13:09:01 -08:00
parent 77f1b1f0fe
commit edb973fadc
8 changed files with 174 additions and 72 deletions

View file

@ -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
*/

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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
View file

@ -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
*/

View file

@ -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)
{