# Copyright (C) 2006 Alessandro Di Marco # # LazyCD is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License as published by the Free Software # Foundation; version 2 of the License. # # LazyCD is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along # with LazyCD; if not, write to the Free Software Foundation, Inc., 51 # Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # --- old/bash-3.1/execute_cmd.c 2005-11-05 20:37:21.000000000 +0100 +++ new/bash-3.1/execute_cmd.c 2006-12-18 15:45:03.000000000 +0100 @@ -3511,6 +3511,99 @@ } } +#define IN_TRIG "/.getin" +#define OUT_TRIG "/.getout" + +#define ADD_TRIGGER(buf, path, name) \ + strcpy ((buf), "( builtin cd \""); \ + strcat ((buf), (path)); \ + strcat ((buf), "\" ; ."); \ + strcat ((buf), (name)); \ + strcat ((buf), " )"); + +static char * +build_trigger_list (old, olde, new, newe) + char *old, *olde, *new, *newe; +{ + char *buf, *pos, *pos1; + + buf = (char *)xmalloc (strlen (olde) + sizeof IN_TRIG + + strlen (newe) + sizeof OUT_TRIG + 49); + + strcpy (buf, "( "); + pos1 = pos = buf + 2; + + strcpy (pos, old); + strcat (pos, OUT_TRIG); + + if (executable_file (pos)) + { + ADD_TRIGGER(pos, olde, OUT_TRIG); + pos1 = pos + strlen (pos); + + strcat (pos, " && "); + pos = pos1 + 4; + } + + strcpy (pos, new); + strcat (pos, IN_TRIG); + + if (executable_file (pos)) + { + ADD_TRIGGER(pos, newe, IN_TRIG); + pos1 = pos + strlen (pos); + } + + strcpy (pos1, " )"); + + if (strlen (buf) == 4) + { + xfree (buf); + buf = NULL; + } + + xfree(olde); + xfree(newe); + + return buf; +} + +static char * +escape_string (string) + char *string; +{ + char *result; + int i, j; + + for (j = i = 0; string[i]; i++) + switch (string[i]) + { + case '$': + case '`': + case '"': + case '\\': + j++; + } + + result = (char *)xmalloc (i + j + 1); + + for (j = i = 0; string[i]; j++, i++) + switch (string[i]) + { + case '$': + case '`': + case '"': + case '\\': + result[j++] = '\\'; + default: + result[j] = string[i]; + } + + result[j] = string[i]; + + return result; +} + /* Execute a simple command that is hopefully defined in a disk file somewhere. @@ -3539,8 +3632,8 @@ struct fd_bitmap *fds_to_close; int cmdflags; { - char *pathname, *command, **args; - int nofork; + char *lazycd_name, *pathname, *command, **args; + int nofork, lazycd_result = 0, lazycd = 0; pid_t pid; nofork = (cmdflags & CMD_NO_FORK); /* Don't fork, just exec, if no pipes */ @@ -3569,6 +3662,59 @@ { maybe_make_export_env (); put_command_name_into_env (command); + lazycd_name = command; + } + else + lazycd_name = pathname; + + if (!find_variable ("LAZY_DISABLE") && is_directory (lazycd_name)) + { + sh_builtin_func_t *builtin; + char *oldpwd; + + /* lazycd patch by Alessandro Di Marco + * for Amiga (and some Mac) nostalgics only! ;) + */ + + lazycd = 1; + oldpwd = getcwd (0,0); + + builtin = find_shell_builtin ("cd"); + words = make_word_list (make_bare_word ("cd"), + make_word_list (make_bare_word (lazycd_name), + NULL)); + + lazycd_result = execute_builtin (builtin, words, 0, 0); + dispose_words (words); + + if (!lazycd_result) + { + char *newpwd = getcwd (0,0); + + if (!oldpwd || !newpwd) + lazycd_result = 1; + else + { + char *cmd = build_trigger_list (oldpwd, + escape_string(oldpwd), + newpwd, + escape_string(newpwd)); + if (cmd) + { + words = make_word_list (make_bare_word ("sh"), + make_word_list (make_bare_word ("-c"), + make_word_list (make_bare_word (cmd), + NULL))); + xfree (cmd); + } + else /* trig nothing */ + lazycd = 2; + } + + xfree (newpwd); + } + + xfree (oldpwd); } /* We have to make the child before we check for the non-existence @@ -3636,6 +3782,14 @@ if (async) interactive = old_interactive; + if (lazycd) + { + if (lazycd_result || lazycd == 2) + exit (lazycd_result); + + command = "/bin/sh"; + } + if (command == 0) { internal_error (_("%s: command not found"), pathname); @@ -3651,6 +3805,10 @@ else { parent_return: + + if (lazycd == 1 && !lazycd_result) + dispose_words (words); + /* Make sure that the pipes are closed in the parent. */ close_pipes (pipe_in, pipe_out); #if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)