Permalink
Browse files

Hack around xdm's dumb assumption that the login shell is POSIX compl…

…iant so we no longer kill OpenSUSE


#367
Also fix some formatting
  • Loading branch information...
ridiculousfish committed Jan 4, 2013
1 parent 77f1b1f commit edb973fadc8d359aa212999d8f447b0de9589789
Showing with 174 additions and 72 deletions.
  1. +2 −2 complete.cpp
  2. +8 −8 env_universal.cpp
  3. +113 −0 expand.cpp
  4. +7 −0 expand.h
  5. +30 −44 fish.cpp
  6. +13 −0 parser.cpp
  7. +0 −17 util.h
  8. +1 −1 wutil.cpp
View
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
{
}
+
View
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
*/
Oops, something went wrong.

0 comments on commit edb973f

Please sign in to comment.