Skip to content

Commit

Permalink
glob: don't raise error for unknown user with '~'
Browse files Browse the repository at this point in the history
* A tilde can optionally be followed by a username
* If a provided username is not found, treat the input as no-match instead of raising an error
* This is consistent with Linux/bash, OpenBSD/ksh and the perl builtin glob() function
* If '~' appears without a username, it is substituted for the current user's home directory

%echo ~mail/a # valid user
/var/mail/a
%echo ~mayel/a # not found
~mayel/a
%echo ~/a
/home/pi/a
  • Loading branch information
mknos authored Dec 9, 2024
1 parent 8f84db3 commit 4c50e2b
Showing 1 changed file with 28 additions and 19 deletions.
47 changes: 28 additions & 19 deletions bin/glob
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ use File::Spec;

use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

$VERSION = 1.2_06;
$VERSION = 1.2_07;
@ISA = qw(Exporter);
@EXPORT = qw(&glob);
@EXPORT_OK = qw(dirsep rootpat curdir parentdir hidedotfiles);
Expand Down Expand Up @@ -211,20 +211,29 @@ sub match_glob {
@errors = ();

# check for and do tilde expansion
if ( /^\~([^${dirsep}]*)/ ) {
if ( s/\A\~([^${dirsep}]*)// ) {
my $usr = $1;
my $usrdir = (length $usr)
? (getpwnam($usr))[7]
: (defined $ENV{HOME} ? $ENV{HOME}
: (getpwuid($<))[7]);
push @errors, "Unknown user: $usr" unless $usrdir;

my $dir;
if (length $usr) {
s/\A\~\Q$usr\E/$usrdir/;
my @pwent = getpwnam $usr;
unless (@pwent) { # username not found
return join('', '~', $usr, $_);
}
$dir = $pwent[7];
}
else {
s/\A\~/$usrdir/;
else { # bare '~'
my @pwent = getpwuid $<;
if (@pwent) {
$dir = $pwent[7];
}
elsif (defined $ENV{'HOME'}) {
$dir = $ENV{'HOME'};
}
else {
push @errors, 'Failed to locate home directory';
}
}
$_ = join('', $dir, $_);
}

# If there's no wildcards, just return it
Expand Down Expand Up @@ -257,10 +266,10 @@ sub match_glob {

if ( $comps[0] =~ /($rootpat)/ ) {
shift(@comps);
@res = &recurseglob( "$1$dirsep", "$1$dirsep" , @comps );
@res = recurseglob( "$1$dirsep", "$1$dirsep" , @comps );
}
else {
@res = &recurseglob( $curdir, '' , @comps );
@res = recurseglob( $curdir, '' , @comps );
}

$matched = @res;
Expand Down Expand Up @@ -298,7 +307,7 @@ sub recurseglob {
foreach (@names) {
if ( m{$regex} ) {
if ( $_ ne "$curdir" and $_ ne "$parentdir") {
unshift(@res, &recurseglob( "$dir$dirsep$_",
unshift(@res, recurseglob( "$dir$dirsep$_",
"$dirname$_$dirsep",
@comps ));
}
Expand Down Expand Up @@ -344,7 +353,7 @@ sub explode_glob {
local $_ = shift;

# Escape special characters and sequences
$_ = &escape_glob($_);
$_ = escape_glob($_);

# Recursively handle nested '{}' sub-globs
while ( $nested and
Expand Down Expand Up @@ -375,7 +384,7 @@ sub explode_glob {

# Unescape special characters and sequences
for (@elements) {
$_ = &unescape_glob($_) for ( ref($_) ? @$_ : ($_) );
$_ = unescape_glob($_) for ( ref($_) ? @$_ : ($_) );
}

# Return the result now if there is only one element
Expand Down Expand Up @@ -415,8 +424,8 @@ sub glob {
my @globbed = ();
my @errmsgs = ();
my $matches = 0;
for (explode_glob $_) {
my @found = &match_glob($_);
for (explode_glob($_)) {
my @found = match_glob($_);
$matches += $matched;
unless (!$matched and /(?:^|[^\\])[*?\[\]]/) {
push @globbed, (@found ? @found : $_);
Expand All @@ -437,7 +446,7 @@ if (!caller() || caller(0) =~ /^(PerlPowerTools::Packed|PAR)$/ || caller(1) eq '
my @globbed = ();
my @errmsgs = ();
for (@ARGV) {
push @globbed, &glob($_);
push @globbed, FastGlob::glob($_);
push @errmsgs, @errors if (@errors);
}
$\ = $opt_0 ? "\0" : "\n";
Expand Down

0 comments on commit 4c50e2b

Please sign in to comment.