commit bash-20040429 snapshot

This commit is contained in:
Chet Ramey
2011-12-03 12:57:04 -05:00
parent de8913bd20
commit c6d91e17e5
12 changed files with 2574 additions and 32 deletions
+27
View File
@@ -9393,3 +9393,30 @@ subst.c
lib/readline/doc/rluser.texi
- fix error in description of emacs-mode C-xC-e command (uses $VISUAL
instead of $FCEDIT)
4/28
----
support/bashbug.sh
- integrate a patch from Stefan Nordhausen
<nordhaus@informatik.hu-berlin.de> that reduces race conditions
by using a temporary directory inside $TMPDIR and creating the
temp files in that
4/30
----
builtins/common.c
- use pathconf(".", _PC_PATH_MAX) where available to size the argument
to getcwd() rather than using a straight PATH_MAX
builtins/cd.def
- if get_working_directory fails and returns null (causing resetpwd
to return NULL), use set_working_directory to set $PWD to the
absolute pathname for which chdir just succeeded
5/1
---
lib/readline/vi_mode.c
- in rl_vi_change_to, call _rl_vi_set_last with rl_numeric_arg instead
of `last', since they're equal at call time and rl_vi_domove can
change rl_numeric_arg (which vi apparently updates). Fixes redo bug
of `c2....' reported by Marion Berryman <mwberryman@copper.net>
+25
View File
@@ -9387,3 +9387,28 @@ subst.c
string_list_dollar_star if the only quoting is Q_HERE_DOCUMENT --
quoted here documents are like double quoting, but not exactly
- analogous changes to list_remove_pattern and pos_params
4/24
----
lib/readline/doc/rluser.texi
- fix error in description of emacs-mode C-xC-e command (uses $VISUAL
instead of $FCEDIT)
4/28
----
support/bashbug.sh
- integrate a patch from Stefan Nordhausen
<nordhaus@informatik.hu-berlin.de> that reduces race conditions
by using a temporary directory inside $TMPDIR and creating the
temp files in that
4/30
----
builtins/common.c
- use pathconf(".", _PC_PATH_MAX) where available to size the argument
to getcwd() rather than using a straight PATH_MAX
builtins/cd.def
- if get_working_directory fails and returns null (causing resetpwd
to return NULL), use set_working_directory to set $PWD to the
absolute pathname for which chdir just succeeded
+20 -10
View File
@@ -377,7 +377,7 @@ change_to_directory (newdir, nolinks)
int nolinks;
{
char *t, *tdir;
int err, canon_failed;
int err, canon_failed, r;
tdir = (char *)NULL;
@@ -412,7 +412,11 @@ change_to_directory (newdir, nolinks)
resolved path doesn't exist), fail immediately. */
if (posixly_correct && nolinks == 0 && canon_failed)
{
#if defined ENAMETOOLONG
if (errno != ENOENT && errno != ENAMETOOLONG)
#else
if (errno != ENOENT)
#endif
errno = ENOTDIR;
return (0);
}
@@ -423,12 +427,13 @@ change_to_directory (newdir, nolinks)
/* If canonicalization failed, but the chdir succeeded, reset the
shell's idea of the_current_working_directory. */
if (canon_failed)
resetpwd ("cd");
else
{
FREE (the_current_working_directory);
the_current_working_directory = tdir;
t = resetpwd ("cd");
if (t == 0)
set_working_directory (tdir);
}
else
set_working_directory (tdir);
return (1);
}
@@ -439,23 +444,28 @@ change_to_directory (newdir, nolinks)
return (0);
err = errno;
free (tdir);
/* We're not in physical mode (nolinks == 0), but we failed to change to
the canonicalized directory name (TDIR). Try what the user passed
verbatim. If we succeed, reinitialize the_current_working_directory. */
if (chdir (newdir) == 0)
{
tdir = resetpwd ("cd");
FREE (tdir);
t = resetpwd ("cd");
if (t == 0)
set_working_directory (tdir);
else
free (t);
return (1);
r = 1;
}
else
{
errno = err;
return (0);
r = 0;
}
free (tdir);
return r;
}
/* Code for cd spelling correction. Original patch submitted by
+484
View File
@@ -0,0 +1,484 @@
This file is cd.def, from which is created cd.c. It implements the
builtins "cd" and "pwd" in Bash.
Copyright (C) 1987-2003 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash 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; either version 2, or (at your option) any later
version.
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
$PRODUCES cd.c
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include "../bashtypes.h"
#include "posixdir.h"
#include "posixstat.h"
#ifndef _MINIX
#include <sys/param.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../bashintl.h"
#include <errno.h>
#include <tilde/tilde.h>
#include "../shell.h"
#include "../flags.h"
#include "maxpath.h"
#include "common.h"
#include "bashgetopt.h"
#if !defined (errno)
extern int errno;
#endif /* !errno */
extern int posixly_correct;
extern int array_needs_making;
extern char *bash_getcwd_errstr;
static int bindpwd __P((int));
static int change_to_directory __P((char *, int));
static char *cdspell __P((char *));
/* Change this to 1 to get cd spelling correction by default. */
int cdspelling = 0;
int cdable_vars;
$BUILTIN cd
$FUNCTION cd_builtin
$SHORT_DOC cd [-L|-P] [dir]
Change the current directory to DIR. The variable $HOME is the
default DIR. The variable CDPATH defines the search path for
the directory containing DIR. Alternative directory names in CDPATH
are separated by a colon (:). A null directory name is the same as
the current directory, i.e. `.'. If DIR begins with a slash (/),
then CDPATH is not used. If the directory is not found, and the
shell option `cdable_vars' is set, then try the word as a variable
name. If that variable has a value, then cd to the value of that
variable. The -P option says to use the physical directory structure
instead of following symbolic links; the -L option forces symbolic links
to be followed.
$END
static int
bindpwd (no_symlinks)
int no_symlinks;
{
char *dirname, *pwdvar;
int old_anm;
SHELL_VAR *tvar;
#define tcwd the_current_working_directory
dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
: get_working_directory ("cd");
#undef tcwd
old_anm = array_needs_making;
pwdvar = get_string_value ("PWD");
tvar = bind_variable ("OLDPWD", pwdvar);
if (old_anm == 0 && array_needs_making && exported_p (tvar))
{
update_export_env_inplace ("OLDPWD=", 7, pwdvar);
array_needs_making = 0;
}
tvar = bind_variable ("PWD", dirname);
if (old_anm == 0 && array_needs_making && exported_p (tvar))
{
update_export_env_inplace ("PWD=", 4, dirname);
array_needs_making = 0;
}
if (dirname && dirname != the_current_working_directory)
free (dirname);
return (EXECUTION_SUCCESS);
}
/* Call get_working_directory to reset the value of
the_current_working_directory () */
static char *
resetpwd (caller)
char *caller;
{
char *tdir;
FREE (the_current_working_directory);
the_current_working_directory = (char *)NULL;
tdir = get_working_directory (caller);
return (tdir);
}
#define LCD_DOVARS 0x001
#define LCD_DOSPELL 0x002
#define LCD_PRINTPATH 0x004
#define LCD_FREEDIRNAME 0x010
/* This builtin is ultimately the way that all user-visible commands should
change the current working directory. It is called by cd_to_string (),
so the programming interface is simple, and it handles errors and
restrictions properly. */
int
cd_builtin (list)
WORD_LIST *list;
{
char *dirname, *cdpath, *path, *temp;
int path_index, no_symlinks, opt, lflag;
#if defined (RESTRICTED_SHELL)
if (restricted)
{
sh_restricted ((char *)NULL);
return (EXECUTION_FAILURE);
}
#endif /* RESTRICTED_SHELL */
no_symlinks = no_symbolic_links;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "LP")) != -1)
{
switch (opt)
{
case 'P':
no_symlinks = 1;
break;
case 'L':
no_symlinks = 0;
break;
default:
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
list = loptend;
lflag = (cdable_vars ? LCD_DOVARS : 0) |
((interactive && cdspelling) ? LCD_DOSPELL : 0);
if (list == 0)
{
/* `cd' without arguments is equivalent to `cd $HOME' */
dirname = get_string_value ("HOME");
if (dirname == 0)
{
builtin_error (_("HOME not set"));
return (EXECUTION_FAILURE);
}
lflag = 0;
}
else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
{
/* This is `cd -', equivalent to `cd $OLDPWD' */
dirname = get_string_value ("OLDPWD");
if (dirname == 0)
{
builtin_error (_("OLDPWD not set"));
return (EXECUTION_FAILURE);
}
#if 0
lflag = interactive ? LCD_PRINTPATH : 0;
#else
lflag = LCD_PRINTPATH; /* According to SUSv3 */
#endif
}
else if (absolute_pathname (list->word->word))
dirname = list->word->word;
else if (cdpath = get_string_value ("CDPATH"))
{
dirname = list->word->word;
/* Find directory in $CDPATH. */
path_index = 0;
while (path = extract_colon_unit (cdpath, &path_index))
{
/* OPT is 1 if the path element is non-empty */
opt = path[0] != '\0';
temp = sh_makepath (path, dirname, MP_DOTILDE);
free (path);
if (change_to_directory (temp, no_symlinks))
{
/* POSIX.2 says that if a nonempty directory from CDPATH
is used to find the directory to change to, the new
directory name is echoed to stdout, whether or not
the shell is interactive. */
if (opt && (path = no_symlinks ? temp : the_current_working_directory))
printf ("%s\n", path);
free (temp);
/* Posix.2 says that after using CDPATH, the resultant
value of $PWD will not contain `.' or `..'. */
return (bindpwd (posixly_correct || no_symlinks));
}
else
free (temp);
}
/* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
try the current directory, so we just punt now with an error
message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
is so we don't mistakenly treat a CDPATH value of "" as not
specifying the current directory. */
if (posixly_correct && cdpath[0])
{
builtin_error ("%s: %s", dirname, strerror (ENOENT));
return (EXECUTION_FAILURE);
}
}
else
dirname = list->word->word;
/* When we get here, DIRNAME is the directory to change to. If we
chdir successfully, just return. */
if (change_to_directory (dirname, no_symlinks))
{
if (lflag & LCD_PRINTPATH)
printf ("%s\n", dirname);
return (bindpwd (no_symlinks));
}
/* If the user requests it, then perhaps this is the name of
a shell variable, whose value contains the directory to
change to. */
if (lflag & LCD_DOVARS)
{
temp = get_string_value (dirname);
if (temp && change_to_directory (temp, no_symlinks))
{
printf ("%s\n", temp);
return (bindpwd (no_symlinks));
}
}
/* If the user requests it, try to find a directory name similar in
spelling to the one requested, in case the user made a simple
typo. This is similar to the UNIX 8th and 9th Edition shells. */
if (lflag & LCD_DOSPELL)
{
temp = cdspell (dirname);
if (temp && change_to_directory (temp, no_symlinks))
{
printf ("%s\n", temp);
return (bindpwd (no_symlinks));
}
else
FREE (temp);
}
builtin_error ("%s: %s", dirname, strerror (errno));
return (EXECUTION_FAILURE);
}
$BUILTIN pwd
$FUNCTION pwd_builtin
$SHORT_DOC pwd [-PL]
Print the current working directory. With the -P option, pwd prints
the physical directory, without any symbolic links; the -L option
makes pwd follow symbolic links.
$END
/* Non-zero means that pwd always prints the physical directory, without
symbolic links. */
static int verbatim_pwd;
/* Print the name of the current working directory. */
int
pwd_builtin (list)
WORD_LIST *list;
{
char *directory;
int opt;
verbatim_pwd = no_symbolic_links;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "LP")) != -1)
{
switch (opt)
{
case 'P':
verbatim_pwd = 1;
break;
case 'L':
verbatim_pwd = 0;
break;
default:
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
list = loptend;
#define tcwd the_current_working_directory
directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
: get_working_directory ("pwd");
/* Try again using getcwd() if canonicalization fails (for instance, if
the file system has changed state underneath bash). */
if (tcwd && directory == 0)
directory = resetpwd ("pwd");
#undef tcwd
if (directory)
{
printf ("%s\n", directory);
if (directory != the_current_working_directory)
free (directory);
fflush (stdout);
if (ferror (stdout))
{
builtin_error (_("write error: %s"), strerror (errno));
clearerr (stdout);
return (EXECUTION_FAILURE);
}
return (EXECUTION_SUCCESS);
}
else
return (EXECUTION_FAILURE);
}
/* Do the work of changing to the directory NEWDIR. Handle symbolic
link following, etc. This function *must* return with
the_current_working_directory either set to NULL (in which case
getcwd() will eventually be called), or set to a string corresponding
to the working directory. Return 1 on success, 0 on failure. */
static int
change_to_directory (newdir, nolinks)
char *newdir;
int nolinks;
{
char *t, *tdir;
int err, canon_failed;
tdir = (char *)NULL;
if (the_current_working_directory == 0)
{
t = get_working_directory ("chdir");
FREE (t);
}
t = make_absolute (newdir, the_current_working_directory);
/* TDIR is either the canonicalized absolute pathname of NEWDIR
(nolinks == 0) or the absolute physical pathname of NEWDIR
(nolinks != 0). */
tdir = nolinks ? sh_physpath (t, 0)
: sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
/* Use the canonicalized version of NEWDIR, or, if canonicalization
failed, use the non-canonical form. */
canon_failed = 0;
if (tdir && *tdir)
free (t);
else
{
FREE (tdir);
tdir = t;
canon_failed = 1;
}
/* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
returns NULL (because it checks the path, it will return NULL if the
resolved path doesn't exist), fail immediately. */
if (posixly_correct && nolinks == 0 && canon_failed)
{
if (errno != ENOENT)
errno = ENOTDIR;
return (0);
}
/* If the chdir succeeds, update the_current_working_directory. */
if (chdir (nolinks ? newdir : tdir) == 0)
{
/* If canonicalization failed, but the chdir succeeded, reset the
shell's idea of the_current_working_directory. */
if (canon_failed)
resetpwd ("cd");
else
{
FREE (the_current_working_directory);
the_current_working_directory = tdir;
}
return (1);
}
/* We failed to change to the appropriate directory name. If we tried
what the user passed (nolinks != 0), punt now. */
if (nolinks)
return (0);
err = errno;
free (tdir);
/* We're not in physical mode (nolinks == 0), but we failed to change to
the canonicalized directory name (TDIR). Try what the user passed
verbatim. If we succeed, reinitialize the_current_working_directory. */
if (chdir (newdir) == 0)
{
tdir = resetpwd ("cd");
FREE (tdir);
return (1);
}
else
{
errno = err;
return (0);
}
}
/* Code for cd spelling correction. Original patch submitted by
Neil Russel (caret@c-side.com). */
static char *
cdspell (dirname)
char *dirname;
{
int n;
char *guess;
n = (strlen (dirname) * 3 + 1) / 2 + 1;
guess = (char *)xmalloc (n);
switch (spname (dirname, guess))
{
case -1:
default:
free (guess);
return (char *)NULL;
case 0:
case 1:
return guess;
}
}
+497
View File
@@ -0,0 +1,497 @@
This file is cd.def, from which is created cd.c. It implements the
builtins "cd" and "pwd" in Bash.
Copyright (C) 1987-2003 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash 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; either version 2, or (at your option) any later
version.
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
$PRODUCES cd.c
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include "../bashtypes.h"
#include "posixdir.h"
#include "posixstat.h"
#ifndef _MINIX
#include <sys/param.h>
#endif
#include <stdio.h>
#include "../bashansi.h"
#include "../bashintl.h"
#include <errno.h>
#include <tilde/tilde.h>
#include "../shell.h"
#include "../flags.h"
#include "maxpath.h"
#include "common.h"
#include "bashgetopt.h"
#if !defined (errno)
extern int errno;
#endif /* !errno */
extern int posixly_correct;
extern int array_needs_making;
extern char *bash_getcwd_errstr;
static int bindpwd __P((int));
static int change_to_directory __P((char *, int));
static char *cdspell __P((char *));
/* Change this to 1 to get cd spelling correction by default. */
int cdspelling = 0;
int cdable_vars;
$BUILTIN cd
$FUNCTION cd_builtin
$SHORT_DOC cd [-L|-P] [dir]
Change the current directory to DIR. The variable $HOME is the
default DIR. The variable CDPATH defines the search path for
the directory containing DIR. Alternative directory names in CDPATH
are separated by a colon (:). A null directory name is the same as
the current directory, i.e. `.'. If DIR begins with a slash (/),
then CDPATH is not used. If the directory is not found, and the
shell option `cdable_vars' is set, then try the word as a variable
name. If that variable has a value, then cd to the value of that
variable. The -P option says to use the physical directory structure
instead of following symbolic links; the -L option forces symbolic links
to be followed.
$END
static int
bindpwd (no_symlinks)
int no_symlinks;
{
char *dirname, *pwdvar;
int old_anm;
SHELL_VAR *tvar;
#define tcwd the_current_working_directory
dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
: get_working_directory ("cd");
#undef tcwd
old_anm = array_needs_making;
pwdvar = get_string_value ("PWD");
tvar = bind_variable ("OLDPWD", pwdvar);
if (old_anm == 0 && array_needs_making && exported_p (tvar))
{
update_export_env_inplace ("OLDPWD=", 7, pwdvar);
array_needs_making = 0;
}
tvar = bind_variable ("PWD", dirname);
if (old_anm == 0 && array_needs_making && exported_p (tvar))
{
update_export_env_inplace ("PWD=", 4, dirname);
array_needs_making = 0;
}
if (dirname && dirname != the_current_working_directory)
free (dirname);
return (EXECUTION_SUCCESS);
}
/* Call get_working_directory to reset the value of
the_current_working_directory () */
static char *
resetpwd (caller)
char *caller;
{
char *tdir;
FREE (the_current_working_directory);
the_current_working_directory = (char *)NULL;
tdir = get_working_directory (caller);
return (tdir);
}
#define LCD_DOVARS 0x001
#define LCD_DOSPELL 0x002
#define LCD_PRINTPATH 0x004
#define LCD_FREEDIRNAME 0x010
/* This builtin is ultimately the way that all user-visible commands should
change the current working directory. It is called by cd_to_string (),
so the programming interface is simple, and it handles errors and
restrictions properly. */
int
cd_builtin (list)
WORD_LIST *list;
{
char *dirname, *cdpath, *path, *temp;
int path_index, no_symlinks, opt, lflag;
#if defined (RESTRICTED_SHELL)
if (restricted)
{
sh_restricted ((char *)NULL);
return (EXECUTION_FAILURE);
}
#endif /* RESTRICTED_SHELL */
no_symlinks = no_symbolic_links;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "LP")) != -1)
{
switch (opt)
{
case 'P':
no_symlinks = 1;
break;
case 'L':
no_symlinks = 0;
break;
default:
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
list = loptend;
lflag = (cdable_vars ? LCD_DOVARS : 0) |
((interactive && cdspelling) ? LCD_DOSPELL : 0);
if (list == 0)
{
/* `cd' without arguments is equivalent to `cd $HOME' */
dirname = get_string_value ("HOME");
if (dirname == 0)
{
builtin_error (_("HOME not set"));
return (EXECUTION_FAILURE);
}
lflag = 0;
}
else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
{
/* This is `cd -', equivalent to `cd $OLDPWD' */
dirname = get_string_value ("OLDPWD");
if (dirname == 0)
{
builtin_error (_("OLDPWD not set"));
return (EXECUTION_FAILURE);
}
#if 0
lflag = interactive ? LCD_PRINTPATH : 0;
#else
lflag = LCD_PRINTPATH; /* According to SUSv3 */
#endif
}
else if (absolute_pathname (list->word->word))
dirname = list->word->word;
else if (cdpath = get_string_value ("CDPATH"))
{
dirname = list->word->word;
/* Find directory in $CDPATH. */
path_index = 0;
while (path = extract_colon_unit (cdpath, &path_index))
{
/* OPT is 1 if the path element is non-empty */
opt = path[0] != '\0';
temp = sh_makepath (path, dirname, MP_DOTILDE);
free (path);
if (change_to_directory (temp, no_symlinks))
{
/* POSIX.2 says that if a nonempty directory from CDPATH
is used to find the directory to change to, the new
directory name is echoed to stdout, whether or not
the shell is interactive. */
if (opt && (path = no_symlinks ? temp : the_current_working_directory))
printf ("%s\n", path);
free (temp);
/* Posix.2 says that after using CDPATH, the resultant
value of $PWD will not contain `.' or `..'. */
return (bindpwd (posixly_correct || no_symlinks));
}
else
free (temp);
}
/* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
try the current directory, so we just punt now with an error
message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
is so we don't mistakenly treat a CDPATH value of "" as not
specifying the current directory. */
if (posixly_correct && cdpath[0])
{
builtin_error ("%s: %s", dirname, strerror (ENOENT));
return (EXECUTION_FAILURE);
}
}
else
dirname = list->word->word;
/* When we get here, DIRNAME is the directory to change to. If we
chdir successfully, just return. */
if (change_to_directory (dirname, no_symlinks))
{
if (lflag & LCD_PRINTPATH)
printf ("%s\n", dirname);
return (bindpwd (no_symlinks));
}
/* If the user requests it, then perhaps this is the name of
a shell variable, whose value contains the directory to
change to. */
if (lflag & LCD_DOVARS)
{
temp = get_string_value (dirname);
if (temp && change_to_directory (temp, no_symlinks))
{
printf ("%s\n", temp);
return (bindpwd (no_symlinks));
}
}
/* If the user requests it, try to find a directory name similar in
spelling to the one requested, in case the user made a simple
typo. This is similar to the UNIX 8th and 9th Edition shells. */
if (lflag & LCD_DOSPELL)
{
temp = cdspell (dirname);
if (temp && change_to_directory (temp, no_symlinks))
{
printf ("%s\n", temp);
return (bindpwd (no_symlinks));
}
else
FREE (temp);
}
builtin_error ("%s: %s", dirname, strerror (errno));
return (EXECUTION_FAILURE);
}
$BUILTIN pwd
$FUNCTION pwd_builtin
$SHORT_DOC pwd [-PL]
Print the current working directory. With the -P option, pwd prints
the physical directory, without any symbolic links; the -L option
makes pwd follow symbolic links.
$END
/* Non-zero means that pwd always prints the physical directory, without
symbolic links. */
static int verbatim_pwd;
/* Print the name of the current working directory. */
int
pwd_builtin (list)
WORD_LIST *list;
{
char *directory;
int opt;
verbatim_pwd = no_symbolic_links;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "LP")) != -1)
{
switch (opt)
{
case 'P':
verbatim_pwd = 1;
break;
case 'L':
verbatim_pwd = 0;
break;
default:
builtin_usage ();
return (EXECUTION_FAILURE);
}
}
list = loptend;
#define tcwd the_current_working_directory
directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
: get_working_directory ("pwd");
/* Try again using getcwd() if canonicalization fails (for instance, if
the file system has changed state underneath bash). */
if (tcwd && directory == 0)
directory = resetpwd ("pwd");
#undef tcwd
if (directory)
{
printf ("%s\n", directory);
if (directory != the_current_working_directory)
free (directory);
fflush (stdout);
if (ferror (stdout))
{
builtin_error (_("write error: %s"), strerror (errno));
clearerr (stdout);
return (EXECUTION_FAILURE);
}
return (EXECUTION_SUCCESS);
}
else
return (EXECUTION_FAILURE);
}
/* Do the work of changing to the directory NEWDIR. Handle symbolic
link following, etc. This function *must* return with
the_current_working_directory either set to NULL (in which case
getcwd() will eventually be called), or set to a string corresponding
to the working directory. Return 1 on success, 0 on failure. */
static int
change_to_directory (newdir, nolinks)
char *newdir;
int nolinks;
{
char *t, *tdir;
int err, canon_failed, r;
tdir = (char *)NULL;
if (the_current_working_directory == 0)
{
t = get_working_directory ("chdir");
FREE (t);
}
t = make_absolute (newdir, the_current_working_directory);
/* TDIR is either the canonicalized absolute pathname of NEWDIR
(nolinks == 0) or the absolute physical pathname of NEWDIR
(nolinks != 0). */
tdir = nolinks ? sh_physpath (t, 0)
: sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
/* Use the canonicalized version of NEWDIR, or, if canonicalization
failed, use the non-canonical form. */
canon_failed = 0;
if (tdir && *tdir)
free (t);
else
{
FREE (tdir);
tdir = t;
canon_failed = 1;
}
/* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
returns NULL (because it checks the path, it will return NULL if the
resolved path doesn't exist), fail immediately. */
if (posixly_correct && nolinks == 0 && canon_failed)
{
#if defined ENAMETOOLONG
if (errno != ENOENT && errno != ENAMETOOLONG)
#else
if (errno != ENOENT)
#endif
errno = ENOTDIR;
return (0);
}
/* If the chdir succeeds, update the_current_working_directory. */
if (chdir (nolinks ? newdir : tdir) == 0)
{
/* If canonicalization failed, but the chdir succeeded, reset the
shell's idea of the_current_working_directory. */
if (canon_failed)
{
t = resetpwd ("cd");
if (t == 0)
set_working_directory (tdir);
}
else
{
FREE (the_current_working_directory);
the_current_working_directory = tdir;
}
return (1);
}
/* We failed to change to the appropriate directory name. If we tried
what the user passed (nolinks != 0), punt now. */
if (nolinks)
return (0);
err = errno;
/* We're not in physical mode (nolinks == 0), but we failed to change to
the canonicalized directory name (TDIR). Try what the user passed
verbatim. If we succeed, reinitialize the_current_working_directory. */
if (chdir (newdir) == 0)
{
t = resetpwd ("cd");
if (t == 0)
set_working_directory (tdir);
else
free (t);
r = 1;
}
else
{
errno = err;
r = 0;
}
free (tdir);
return r;
}
/* Code for cd spelling correction. Original patch submitted by
Neil Russel (caret@c-side.com). */
static char *
cdspell (dirname)
char *dirname;
{
int n;
char *guess;
n = (strlen (dirname) * 3 + 1) / 2 + 1;
guess = (char *)xmalloc (n);
switch (spname (dirname, guess))
{
case -1:
default:
free (guess);
return (char *)NULL;
case 0:
case 1:
return guess;
}
}
+11 -6
View File
@@ -462,23 +462,28 @@ get_working_directory (for_whom)
char *for_whom;
{
char *directory;
size_t dsize;
if (no_symbolic_links)
{
if (the_current_working_directory)
free (the_current_working_directory);
FREE (the_current_working_directory);
the_current_working_directory = (char *)NULL;
}
if (the_current_working_directory == 0)
{
the_current_working_directory = (char *)xmalloc (PATH_MAX);
#if defined (HAVE_PATHCONF)
dsize = pathconf (".", _PC_PATH_MAX);
#else
dsize = PATH_MAX;
#endif
the_current_working_directory = (char *)xmalloc (dsize+1);
the_current_working_directory[0] = '\0';
directory = getcwd (the_current_working_directory, PATH_MAX);
directory = getcwd (the_current_working_directory, dsize);
if (directory == 0)
{
fprintf (stderr, _("%s: could not get current directory: %s: %s\n"),
fprintf (stderr, _("%s: error retrieving current directory: %s: %s\n"),
(for_whom && *for_whom) ? for_whom : get_name_for_error (),
_(bash_getcwd_errstr), strerror (errno));
+11 -6
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
/* Copyright (C) 1987-2004 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -462,20 +462,25 @@ get_working_directory (for_whom)
char *for_whom;
{
char *directory;
size_t dsize;
if (no_symbolic_links)
{
if (the_current_working_directory)
free (the_current_working_directory);
FREE (the_current_working_directory);
the_current_working_directory = (char *)NULL;
}
if (the_current_working_directory == 0)
{
the_current_working_directory = (char *)xmalloc (PATH_MAX);
#if defined (HAVE_PATHCONF)
dsize = pathconf (".", _PC_PATH_MAX);
#else
dsize = PATH_MAX;
#endif
the_current_working_directory = (char *)xmalloc (dsize+1);
the_current_working_directory[0] = '\0';
directory = getcwd (the_current_working_directory, PATH_MAX);
directory = getcwd (the_current_working_directory, dsize);
if (directory == 0)
{
fprintf (stderr, _("%s: could not get current directory: %s: %s\n"),
+1 -1
View File
@@ -1018,7 +1018,7 @@ rl_vi_change_to (count, key)
/* `C' does not save the text inserted for undoing or redoing. */
if (_rl_uppercase_p (key) == 0)
_rl_vi_doing_insert = 1;
_rl_vi_set_last (key, count, rl_arg_sign);
_rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
rl_vi_insertion_mode (1, key);
}
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -138,7 +138,7 @@ msgstr ""
msgid "OLDPWD not set"
msgstr ""
#: builtins/cd.def:350
#: builtins/cd.def:357
#, c-format
msgid "write error: %s"
msgstr ""
@@ -239,12 +239,12 @@ msgstr ""
msgid "%s: not a shell builtin"
msgstr ""
#: builtins/common.c:481
#: builtins/common.c:486
#, c-format
msgid "%s: could not get current directory: %s: %s\n"
msgid "%s: error retrieving current directory: %s: %s\n"
msgstr ""
#: builtins/common.c:548 builtins/common.c:550
#: builtins/common.c:553 builtins/common.c:555
#, c-format
msgid "%s: ambiguous job spec"
msgstr ""
+4 -4
View File
@@ -138,7 +138,7 @@ msgstr ""
msgid "OLDPWD not set"
msgstr ""
#: builtins/cd.def:350
#: builtins/cd.def:357
#, c-format
msgid "write error: %s"
msgstr ""
@@ -239,12 +239,12 @@ msgstr ""
msgid "%s: not a shell builtin"
msgstr ""
#: builtins/common.c:481
#: builtins/common.c:486
#, c-format
msgid "%s: could not get current directory: %s: %s\n"
msgstr ""
#: builtins/common.c:548 builtins/common.c:550
#: builtins/common.c:553 builtins/common.c:555
#, c-format
msgid "%s: ambiguous job spec"
msgstr ""
@@ -417,7 +417,7 @@ msgstr ""
msgid "%s: history expansion failed"
msgstr ""
#: builtins/jobs.def:102
#: builtins/jobs.def:99
msgid "no other options allowed with `-x'"
msgstr ""
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/bash/bash-current
BUILD_DIR=/usr/local/build/chet/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR