1#ifdef __APPLE__ 2#include <glob.h> 3#include <stdlib.h> 4#include <string.h> 5 6char ** 7glob_filename (const char *pathname) 8{ 9 char **result = NULL; 10 glob_t g; 11 int i; 12 13 if (glob(pathname, 0, NULL, &g) == 0) { 14 result = malloc((g.gl_pathc + 1) * sizeof(char *)); 15 for (i = 0; i < g.gl_pathc; i++) { 16 result[i] = strdup(g.gl_pathv[i]); 17 } 18 result[g.gl_pathc] = NULL; 19 globfree(&g); 20 } 21 22 return result; 23} 24#else 25/* File-name wildcard pattern matching for GNU. 26 Copyright (C) 1985, 1988, 1989, 1990, 1991 Free Software Foundation, Inc. 27 28 This program is free software; you can redistribute it and/or modify 29 it under the terms of the GNU General Public License as published by 30 the Free Software Foundation; either version 1, or (at your option) 31 any later version. 32 33 This program is distributed in the hope that it will be useful, 34 but WITHOUT ANY WARRANTY; without even the implied warranty of 35 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 36 GNU General Public License for more details. 37 38 You should have received a copy of the GNU General Public License 39 along with this program; if not, write to the Free Software 40 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 41 42/* To whomever it may concern: I have never seen the code which most 43 Unix programs use to perform this function. I wrote this from scratch 44 based on specifications for the pattern matching. --RMS. */ 45 46#ifdef SHELL 47#include "config.h" 48#endif /* SHELL */ 49 50#include <sys/types.h> 51 52#if defined (USGr3) && !defined (DIRENT) 53#define DIRENT 54#endif /* USGr3 */ 55#if defined (Xenix) && !defined (SYSNDIR) 56#define SYSNDIR 57#endif /* Xenix */ 58 59#if defined (POSIX) || defined (DIRENT) || defined (__GNU_LIBRARY__) 60#include <dirent.h> 61#define direct dirent 62#define D_NAMLEN(d) strlen((d)->d_name) 63#else /* not POSIX or DIRENT or __GNU_LIBRARY__ */ 64#define D_NAMLEN(d) ((d)->d_namlen) 65#ifdef USG 66#if defined (SYSNDIR) 67#include <sys/ndir.h> 68#else /* SYSNDIR */ 69#include "ndir.h" 70#endif /* not SYSNDIR */ 71#else /* not USG */ 72#include <sys/dir.h> 73#endif /* USG */ 74#endif /* POSIX or DIRENT or __GNU_LIBRARY__ */ 75 76#ifdef __QNX__ 77#define REAL_DIR_ENTRY(dp) (dp->d_stat.st_ino != 0) 78#elif defined (_POSIX_SOURCE) 79/* Posix does not require that the d_ino field be present, and some 80 systems do not provide it. */ 81#define REAL_DIR_ENTRY(dp) 1 82#else 83#define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) 84#endif /* _POSIX_SOURCE */ 85 86#if defined (STDC_HEADERS) || defined (__GNU_LIBRARY__) 87#include <stdlib.h> 88#include <string.h> 89#define STDC_STRINGS 90#else /* STDC_HEADERS or __GNU_LIBRARY__ */ 91 92#if defined (USG) 93#include <string.h> 94#ifndef POSIX 95#include <memory.h> 96#endif /* POSIX */ 97#define STDC_STRINGS 98#else /* not USG */ 99#ifdef NeXT 100#include <string.h> 101#else /* NeXT */ 102#include <strings.h> 103#endif /* NeXT */ 104/* Declaring bcopy causes errors on systems whose declarations are different. 105 If the declaration is omitted, everything works fine. */ 106#endif /* not USG */ 107 108extern char *malloc (); 109extern char *realloc (); 110extern void free (); 111 112#ifndef NULL 113#define NULL 0 114#endif 115#endif /* Not STDC_HEADERS or __GNU_LIBRARY__. */ 116 117#ifdef STDC_STRINGS 118#define bcopy(s, d, n) memcpy ((d), (s), (n)) 119#define index strchr 120#define rindex strrchr 121#endif /* STDC_STRINGS */ 122 123#ifndef alloca 124#ifdef __GNUC__ 125#define alloca __builtin_alloca 126#else /* Not GCC. */ 127#ifdef sparc 128#include <alloca.h> 129#else /* Not sparc. */ 130extern char *alloca (); 131#endif /* sparc. */ 132#endif /* GCC. */ 133#endif 134 135/* Nonzero if '*' and '?' do not match an initial '.' for glob_filename. */ 136int noglob_dot_filenames = 1; 137 138static int glob_match_after_star (); 139 140/* Return nonzero if PATTERN has any special globbing chars in it. */ 141 142int 143glob_pattern_p (pattern) 144 char *pattern; 145{ 146 register char *p = pattern; 147 register char c; 148 int open = 0; 149 150 while ((c = *p++) != '\0') 151 switch (c) 152 { 153 case '?': 154 case '*': 155 return 1; 156 157 case '[': /* Only accept an open brace if there is a close */ 158 open++; /* brace to match it. Bracket expressions must be */ 159 continue; /* complete, according to Posix.2 */ 160 case ']': 161 if (open) 162 return 1; 163 continue; 164 165 case '\\': 166 if (*p++ == '\0') 167 return 0; 168 } 169 170 return 0; 171} 172 173 174/* Match the pattern PATTERN against the string TEXT; 175 return 1 if it matches, 0 otherwise. 176 177 A match means the entire string TEXT is used up in matching. 178 179 In the pattern string, `*' matches any sequence of characters, 180 `?' matches any character, [SET] matches any character in the specified set, 181 [!SET] matches any character not in the specified set. 182 183 A set is composed of characters or ranges; a range looks like 184 character hyphen character (as in 0-9 or A-Z). 185 [0-9a-zA-Z_] is the set of characters allowed in C identifiers. 186 Any other character in the pattern must be matched exactly. 187 188 To suppress the special syntactic significance of any of `[]*?!-\', 189 and match the character exactly, precede it with a `\'. 190 191 If DOT_SPECIAL is nonzero, 192 `*' and `?' do not match `.' at the beginning of TEXT. */ 193 194int 195glob_match (pattern, text, dot_special) 196 char *pattern, *text; 197 int dot_special; 198{ 199 register char *p = pattern, *t = text; 200 register char c; 201 202 while ((c = *p++) != '\0') 203 switch (c) 204 { 205 case '?': 206 if (*t == '\0' || (dot_special && t == text && *t == '.')) 207 return 0; 208 else 209 ++t; 210 break; 211 212 case '\\': 213 if (*p++ != *t++) 214 return 0; 215 break; 216 217 case '*': 218 if (dot_special && t == text && *t == '.') 219 return 0; 220 return glob_match_after_star (p, t); 221 222 case '[': 223 { 224 register char c1 = *t++; 225 int invert; 226 227 if (c1 == '\0') 228 return 0; 229 230 invert = (*p == '!'); 231 232 if (invert) 233 p++; 234 235 c = *p++; 236 while (1) 237 { 238 register char cstart = c, cend = c; 239 240 if (c == '\\') 241 { 242 cstart = *p++; 243 cend = cstart; 244 } 245 246 if (cstart == '\0') 247 return 0; /* Missing ']'. */ 248 249 c = *p++; 250 251 if (c == '-') 252 { 253 cend = *p++; 254 if (cend == '\\') 255 cend = *p++; 256 if (cend == '\0') 257 return 0; 258 c = *p++; 259 } 260 if (c1 >= cstart && c1 <= cend) 261 goto match; 262 if (c == ']') 263 break; 264 } 265 if (!invert) 266 return 0; 267 break; 268 269 match: 270 /* Skip the rest of the [...] construct that already matched. */ 271 while (c != ']') 272 { 273 if (c == '\0') 274 return 0; 275 c = *p++; 276 if (c == '\0') 277 return 0; 278 if (c == '\\') 279 p++; 280 } 281 if (invert) 282 return 0; 283 break; 284 } 285 286 default: 287 if (c != *t++) 288 return 0; 289 } 290 291 return *t == '\0'; 292} 293 294/* Like glob_match, but match PATTERN against any final segment of TEXT. */ 295 296static int 297glob_match_after_star (pattern, text) 298 char *pattern, *text; 299{ 300 register char *p = pattern, *t = text; 301 register char c, c1; 302 303 while ((c = *p++) == '?' || c == '*') 304 if (c == '?' && *t++ == '\0') 305 return 0; 306 307 if (c == '\0') 308 return 1; 309 310 if (c == '\\') 311 c1 = *p; 312 else 313 c1 = c; 314 315 --p; 316 while (1) 317 { 318 if ((c == '[' || *t == c1) && glob_match (p, t, 0)) 319 return 1; 320 if (*t++ == '\0') 321 return 0; 322 } 323} 324 325/* Return a vector of names of files in directory DIR 326 whose names match glob pattern PAT. 327 The names are not in any particular order. 328 Wildcards at the beginning of PAT do not match an initial period 329 if noglob_dot_filenames is nonzero. 330 331 The vector is terminated by an element that is a null pointer. 332 333 To free the space allocated, first free the vector's elements, 334 then free the vector. 335 336 Return NULL if cannot get enough memory to hold the pointer 337 and the names. 338 339 Return -1 if cannot access directory DIR. 340 Look in errno for more information. */ 341 342char ** 343glob_vector (pat, dir) 344 char *pat; 345 char *dir; 346{ 347 struct globval 348 { 349 struct globval *next; 350 char *name; 351 }; 352 353 DIR *d; 354 register struct direct *dp; 355 struct globval *lastlink; 356 register struct globval *nextlink; 357 register char *nextname; 358 unsigned int count; 359 int lose; 360 register char **name_vector = 0; 361 register unsigned int i; 362#ifdef ALLOCA_MISSING 363 struct globval *templink; 364#endif 365 366 d = opendir (dir); 367 if (d == NULL) 368 return (char **) -1; 369 370 lastlink = NULL; 371 count = 0; 372 lose = 0; 373 374 /* Scan the directory, finding all names that match. 375 For each name that matches, allocate a struct globval 376 on the stack and store the name in it. 377 Chain those structs together; lastlink is the front of the chain. */ 378 while (1) 379 { 380#if defined (SHELL) 381 /* Make globbing interruptible in the bash shell. */ 382 extern int interrupt_state; 383 384 if (interrupt_state) 385 { 386 closedir (d); 387 lose = 1; 388 goto lost; 389 } 390#endif /* SHELL */ 391 392 dp = readdir (d); 393 if (dp == NULL) 394 break; 395 if (REAL_DIR_ENTRY (dp) 396 && glob_match (pat, dp->d_name, noglob_dot_filenames)) 397 { 398#ifdef ALLOCA_MISSING 399 nextlink = (struct globval *) malloc (sizeof (struct globval)); 400#else 401 nextlink = (struct globval *) alloca (sizeof (struct globval)); 402#endif 403 nextlink->next = lastlink; 404 i = D_NAMLEN (dp) + 1; 405 nextname = (char *) malloc (i); 406 if (nextname == NULL) 407 { 408 lose = 1; 409 break; 410 } 411 lastlink = nextlink; 412 nextlink->name = nextname; 413 bcopy (dp->d_name, nextname, i); 414 count++; 415 } 416 } 417 closedir (d); 418 419 if (!lose) 420 { 421 name_vector = (char **) malloc ((count + 1) * sizeof (char *)); 422 lose |= name_vector == NULL; 423 } 424 425 /* Have we run out of memory? */ 426#ifdef SHELL 427 lost: 428#endif 429 if (lose) 430 { 431 /* Here free the strings we have got. */ 432 while (lastlink) 433 { 434 free (lastlink->name); 435#ifdef ALLOCA_MISSING 436 templink = lastlink->next; 437 free ((char *) lastlink); 438 lastlink = templink; 439#else 440 lastlink = lastlink->next; 441#endif 442 } 443 return NULL; 444 } 445 446 /* Copy the name pointers from the linked list into the vector. */ 447 for (i = 0; i < count; ++i) 448 { 449 name_vector[i] = lastlink->name; 450#ifdef ALLOCA_MISSING 451 templink = lastlink->next; 452 free ((char *) lastlink); 453 lastlink = templink; 454#else 455 lastlink = lastlink->next; 456#endif 457 } 458 459 name_vector[count] = NULL; 460 return name_vector; 461} 462 463/* Return a new array, replacing ARRAY, which is the concatenation 464 of each string in ARRAY to DIR. 465 Return NULL if out of memory. */ 466 467static char ** 468glob_dir_to_array (dir, array) 469 char *dir, **array; 470{ 471 register unsigned int i, l; 472 int add_slash = 0; 473 char **result; 474 475 l = strlen (dir); 476 if (l == 0) 477 return array; 478 479 if (dir[l - 1] != '/') 480 add_slash++; 481 482 for (i = 0; array[i] != NULL; i++) 483 ; 484 485 result = (char **) malloc ((i + 1) * sizeof (char *)); 486 if (result == NULL) 487 return NULL; 488 489 for (i = 0; array[i] != NULL; i++) 490 { 491 result[i] = (char *) malloc (1 + l + add_slash + strlen (array[i])); 492 if (result[i] == NULL) 493 return NULL; 494 strcpy (result[i], dir); 495 if (add_slash) 496 result[i][l] = '/'; 497 strcpy (result[i] + l + add_slash, array[i]); 498 } 499 result[i] = NULL; 500 501 /* Free the input array. */ 502 for (i = 0; array[i] != NULL; i++) 503 free (array[i]); 504 free ((char *) array); 505 return result; 506} 507 508/* Do globbing on PATHNAME. Return an array of pathnames that match, 509 marking the end of the array with a null-pointer as an element. 510 If no pathnames match, then the array is empty (first element is null). 511 If there isn't enough memory, then return NULL. 512 If a file system error occurs, return -1; `errno' has the error code. 513 514 Wildcards at the beginning of PAT, or following a slash, 515 do not match an initial period if noglob_dot_filenames is nonzero. */ 516 517char ** 518glob_filename (const char *pathname) 519{ 520 char **result; 521 unsigned int result_size; 522 char *directory_name; 523 const char *filename; 524 unsigned int directory_len; 525 526 result = (char **) malloc (sizeof (char *)); 527 result_size = 1; 528 if (result == NULL) 529 return NULL; 530 531 result[0] = NULL; 532 533 /* Find the filename. */ 534 filename = rindex (pathname, '/'); 535 if (filename == NULL) 536 { 537 filename = pathname; 538 directory_name = ""; 539 directory_len = 0; 540 } 541 else 542 { 543 directory_len = (filename - pathname) + 1; 544#ifdef ALLOCA_MISSING 545 directory_name = (char *) malloc (directory_len + 1); 546#else 547 directory_name = (char *) alloca (directory_len + 1); 548#endif 549 bcopy (pathname, directory_name, directory_len); 550 directory_name[directory_len] = '\0'; 551 ++filename; 552 } 553 554 /* If directory_name contains globbing characters, then we 555 have to expand the previous levels. Just recurse. */ 556 if (glob_pattern_p (directory_name)) 557 { 558 char **directories; 559 register unsigned int i; 560 561 if (directory_name[directory_len - 1] == '/') 562 directory_name[directory_len - 1] = '\0'; 563 564 directories = glob_filename (directory_name); 565#ifdef ALLOCA_MISSING 566 free ((char *) directory_name); 567#endif 568 if (directories == NULL) 569 goto memory_error; 570 else if (directories == (char **) -1) 571 return (char **) -1; 572 else if (*directories == NULL) 573 { 574 free ((char *) directories); 575 return (char **) -1; 576 } 577 578 /* We have successfully globbed the preceding directory name. 579 For each name in DIRECTORIES, call glob_vector on it and 580 FILENAME. Concatenate the results together. */ 581 for (i = 0; directories[i] != NULL; i++) 582 { 583 char **temp_results = glob_vector (filename, directories[i]); 584 if (temp_results == NULL) 585 goto memory_error; 586 else if (temp_results == (char **) -1) 587 /* This filename is probably not a directory. Ignore it. */ 588 ; 589 else 590 { 591 char **array = glob_dir_to_array (directories[i], temp_results); 592 register unsigned int l; 593 594 l = 0; 595 while (array[l] != NULL) 596 ++l; 597 598 result = (char **) realloc (result, 599 (result_size + l) * sizeof (char *)); 600 if (result == NULL) 601 goto memory_error; 602 603 for (l = 0; array[l] != NULL; ++l) 604 result[result_size++ - 1] = array[l]; 605 result[result_size - 1] = NULL; 606 free ((char *) array); 607 } 608 } 609 /* Free the directories. */ 610 for (i = 0; directories[i] != NULL; i++) 611 free (directories[i]); 612 free ((char *) directories); 613 614 return result; 615 } 616 617 /* If there is only a directory name, return it. */ 618 if (*filename == '\0') 619 { 620 result = (char **) realloc ((char *) result, 2 * sizeof (char *)); 621 if (result != NULL) 622 { 623 result[0] = (char *) malloc (directory_len + 1); 624 if (result[0] == NULL) 625 { 626#ifdef ALLOCA_MISSING 627 free ((char *) directory_name); 628#endif 629 goto memory_error; 630 } 631 bcopy (directory_name, result[0], directory_len + 1); 632 result[1] = NULL; 633 } 634#ifdef ALLOCA_MISSING 635 free ((char *) directory_name); 636#endif 637 return result; 638 } 639 else 640 { 641 /* Otherwise, just return what glob_vector 642 returns appended to the directory name. */ 643 char **temp_results = glob_vector (filename, 644 (directory_len == 0 645 ? "." : directory_name)); 646 647 if (temp_results == NULL || temp_results == (char **) -1) 648 { 649#ifdef NO_ALLOCA 650 free ((char *) directory_name); 651#endif 652 return temp_results; 653 } 654 655 temp_results = glob_dir_to_array (directory_name, temp_results); 656#ifdef NO_ALLOCA 657 free ((char *) directory_name); 658#endif 659 return temp_results; 660 } 661 662 /* We get to memory error if the program has run out of memory, or 663 if this is the shell, and we have been interrupted. */ 664 memory_error: 665 if (result != NULL) 666 { 667 register unsigned int i; 668 for (i = 0; result[i] != NULL; ++i) 669 free (result[i]); 670 free ((char *) result); 671 } 672#if defined (SHELL) 673 { 674 extern int interrupt_state; 675 676 if (interrupt_state) 677 throw_to_top_level (); 678 } 679#endif /* SHELL */ 680 return NULL; 681} 682 683#ifdef TEST 684 685main (argc, argv) 686 int argc; 687 char **argv; 688{ 689 char **value; 690 int i, optind; 691 692 for (optind = 1; optind < argc; optind++) 693 { 694 value = glob_filename (argv[optind]); 695 if (value == NULL) 696 puts ("virtual memory exhausted"); 697 else if (value == (char **) -1) 698 perror (argv[optind]); 699 else 700 for (i = 0; value[i] != NULL; i++) 701 puts (value[i]); 702 } 703 exit (0); 704} 705 706#endif /* TEST */ 707#endif 708