1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Guido van Rossum. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 #if defined(LIBC_SCCS) && !defined(lint) 37 static char sccsid[] = "@(#)glob.c 5.12 (Berkeley) 6/24/91"; 38 #endif /* LIBC_SCCS and not lint */ 39 /* 40 * Glob: the interface is a superset of the one defined in POSIX 1003.2, 41 * draft 9. 42 * 43 * The [!...] convention to negate a range is supported (SysV, Posix, ksh). 44 * 45 * Optional extra services, controlled by flags not defined by POSIX: 46 * 47 * GLOB_QUOTE: 48 * Escaping convention: \ inhibits any special meaning the following 49 * character might have (except \ at end of string is retained). 50 * GLOB_MAGCHAR: 51 * Set in gl_flags if pattern contained a globbing character. 52 * GLOB_ALTNOT: 53 * Use ^ instead of ! for "not". 54 * gl_matchc: 55 * Number of matches in the current invocation of glob. 56 */ 57 58 #ifdef notdef 59 #include <sys/types.h> 60 #include <sys/param.h> 61 #include <sys/stat.h> 62 #include <dirent.h> 63 #include <ctype.h> 64 typedef void * ptr_t; 65 #endif 66 #ifdef WINNT_NATIVE 67 #pragma warning(disable:4244) 68 #endif /* WINNT_NATIVE */ 69 70 #define Char __Char 71 #include "sh.h" 72 #undef Char 73 #undef QUOTE 74 #undef TILDE 75 #undef META 76 #undef CHAR 77 #undef ismeta 78 #undef Strchr 79 80 #include "glob.h" 81 82 #ifndef S_ISDIR 83 #define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) 84 #endif 85 86 #if !defined(S_ISLNK) && defined(S_IFLNK) 87 #define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK) 88 #endif 89 90 #if !defined(S_ISLNK) && !defined(lstat) 91 #define lstat stat 92 #endif 93 94 typedef unsigned short Char; 95 96 static int glob1 __P((Char *, glob_t *, int)); 97 static int glob2 __P((Char *, Char *, Char *, glob_t *, int)); 98 static int glob3 __P((Char *, Char *, Char *, Char *, 99 glob_t *, int)); 100 static int globextend __P((Char *, glob_t *)); 101 static int match __P((Char *, Char *, Char *, int)); 102 #ifndef __clipper__ 103 static int compare __P((const ptr_t, const ptr_t)); 104 #endif 105 static DIR *Opendir __P((Char *)); 106 #ifdef S_IFLNK 107 static int Lstat __P((Char *, struct stat *)); 108 #endif 109 static int Stat __P((Char *, struct stat *sb)); 110 static Char *Strchr __P((Char *, int)); 111 #ifdef DEBUG 112 static void qprintf __P((Char *)); 113 #endif 114 115 #define DOLLAR '$' 116 #define DOT '.' 117 #define EOS '\0' 118 #define LBRACKET '[' 119 #define NOT '!' 120 #define ALTNOT '^' 121 #define QUESTION '?' 122 #define QUOTE '\\' 123 #define RANGE '-' 124 #define RBRACKET ']' 125 #define SEP '/' 126 #define STAR '*' 127 #define TILDE '~' 128 #define UNDERSCORE '_' 129 130 #define M_META 0x8000 131 #define M_PROTECT 0x4000 132 #define M_MASK 0xffff 133 #define M_ASCII 0x00ff 134 135 #define CHAR(c) ((c)&M_ASCII) 136 #define META(c) ((c)|M_META) 137 #define M_ALL META('*') 138 #define M_END META(']') 139 #define M_NOT META('!') 140 #define M_ALTNOT META('^') 141 #define M_ONE META('?') 142 #define M_RNG META('-') 143 #define M_SET META('[') 144 #define ismeta(c) (((c)&M_META) != 0) 145 146 #ifndef BUFSIZE 147 #define GLOBBUFLEN MAXPATHLEN 148 #else 149 #define GLOBBUFLEN BUFSIZE 150 #endif 151 152 int 153 globcharcoll(c1, c2) 154 int c1, c2; 155 { 156 #if defined(NLS) && defined(LC_COLLATE) && !defined(NOSTRCOLL) 157 char s1[2], s2[2]; 158 159 if (c1 == c2) 160 return (0); 161 /* 162 * From kevin lyda <kevin@suberic.net>: 163 * strcoll does not guarantee case sorting, so we pre-process now: 164 */ 165 if (islower(c1) && isupper(c2)) 166 return (1); 167 s1[0] = c1; 168 s2[0] = c2; 169 s1[1] = s2[1] = '\0'; 170 return strcoll(s1, s2); 171 #else 172 return (c1 - c2); 173 #endif 174 } 175 176 /* 177 * Need to dodge two kernel bugs: 178 * opendir("") != opendir(".") 179 * NAMEI_BUG: on plain files trailing slashes are ignored in some kernels. 180 * POSIX specifies that they should be ignored in directories. 181 */ 182 183 static DIR * 184 Opendir(str) 185 register Char *str; 186 { 187 char buf[GLOBBUFLEN]; 188 register char *dc = buf; 189 #if defined(hpux) || defined(__hpux) 190 struct stat st; 191 #endif 192 193 if (!*str) 194 return (opendir(".")); 195 while ((*dc++ = *str++) != '\0') 196 continue; 197 #if defined(hpux) || defined(__hpux) 198 /* 199 * Opendir on some device files hangs, so avoid it 200 */ 201 if (stat(buf, &st) == -1 || !S_ISDIR(st.st_mode)) 202 return NULL; 203 #endif 204 return (opendir(buf)); 205 } 206 207 #ifdef S_IFLNK 208 static int 209 Lstat(fn, sb) 210 register Char *fn; 211 struct stat *sb; 212 { 213 char buf[GLOBBUFLEN]; 214 register char *dc = buf; 215 216 while ((*dc++ = *fn++) != '\0') 217 continue; 218 # ifdef NAMEI_BUG 219 { 220 int st; 221 222 st = lstat(buf, sb); 223 if (*buf) 224 dc--; 225 return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st); 226 } 227 # else 228 return (lstat(buf, sb)); 229 # endif /* NAMEI_BUG */ 230 } 231 #else 232 #define Lstat Stat 233 #endif /* S_IFLNK */ 234 235 static int 236 Stat(fn, sb) 237 register Char *fn; 238 struct stat *sb; 239 { 240 char buf[GLOBBUFLEN]; 241 register char *dc = buf; 242 243 while ((*dc++ = *fn++) != '\0') 244 continue; 245 #ifdef NAMEI_BUG 246 { 247 int st; 248 249 st = stat(buf, sb); 250 if (*buf) 251 dc--; 252 return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st); 253 } 254 #else 255 return (stat(buf, sb)); 256 #endif /* NAMEI_BUG */ 257 } 258 259 static Char * 260 Strchr(str, ch) 261 Char *str; 262 int ch; 263 { 264 do 265 if (*str == ch) 266 return (str); 267 while (*str++); 268 return (NULL); 269 } 270 271 #ifdef DEBUG 272 static void 273 qprintf(s) 274 Char *s; 275 { 276 Char *p; 277 278 for (p = s; *p; p++) 279 printf("%c", *p & 0xff); 280 printf("\n"); 281 for (p = s; *p; p++) 282 printf("%c", *p & M_PROTECT ? '"' : ' '); 283 printf("\n"); 284 for (p = s; *p; p++) 285 printf("%c", *p & M_META ? '_' : ' '); 286 printf("\n"); 287 } 288 #endif /* DEBUG */ 289 290 static int 291 compare(p, q) 292 const ptr_t p, q; 293 { 294 #if defined(NLS) && !defined(NOSTRCOLL) 295 errno = 0; /* strcoll sets errno, another brain-damage */ 296 297 return (strcoll(*(char **) p, *(char **) q)); 298 #else 299 return (strcmp(*(char **) p, *(char **) q)); 300 #endif /* NLS && !NOSTRCOLL */ 301 } 302 303 /* 304 * The main glob() routine: compiles the pattern (optionally processing 305 * quotes), calls glob1() to do the real pattern matching, and finally 306 * sorts the list (unless unsorted operation is requested). Returns 0 307 * if things went well, nonzero if errors occurred. It is not an error 308 * to find no matches. 309 */ 310 int 311 glob(pattern, flags, errfunc, pglob) 312 const char *pattern; 313 int flags; 314 int (*errfunc) __P((const char *, int)); 315 glob_t *pglob; 316 { 317 int err, oldpathc; 318 Char *bufnext, *bufend, *compilebuf, m_not; 319 const unsigned char *compilepat, *patnext; 320 int c, not; 321 Char patbuf[GLOBBUFLEN + 1], *qpatnext; 322 int no_match; 323 324 patnext = (unsigned char *) pattern; 325 if (!(flags & GLOB_APPEND)) { 326 pglob->gl_pathc = 0; 327 pglob->gl_pathv = NULL; 328 if (!(flags & GLOB_DOOFFS)) 329 pglob->gl_offs = 0; 330 } 331 pglob->gl_flags = flags & ~GLOB_MAGCHAR; 332 pglob->gl_errfunc = errfunc; 333 oldpathc = pglob->gl_pathc; 334 pglob->gl_matchc = 0; 335 336 if (pglob->gl_flags & GLOB_ALTNOT) { 337 not = ALTNOT; 338 m_not = M_ALTNOT; 339 } 340 else { 341 not = NOT; 342 m_not = M_NOT; 343 } 344 345 bufnext = patbuf; 346 bufend = bufnext + GLOBBUFLEN; 347 compilebuf = bufnext; 348 compilepat = patnext; 349 350 no_match = *patnext == not; 351 if (no_match) 352 patnext++; 353 354 if (flags & GLOB_QUOTE) { 355 /* Protect the quoted characters */ 356 while (bufnext < bufend && (c = *patnext++) != EOS) 357 #ifdef DSPMBYTE 358 if (Ismbyte1(c) && *patnext != EOS) 359 { 360 *bufnext++ = (Char) c; 361 *bufnext++ = (Char) *patnext++; 362 } 363 else 364 #endif /* DSPMBYTE */ 365 if (c == QUOTE) { 366 if ((c = *patnext++) == EOS) { 367 c = QUOTE; 368 --patnext; 369 } 370 *bufnext++ = (Char) (c | M_PROTECT); 371 } 372 else 373 *bufnext++ = (Char) c; 374 } 375 else 376 while (bufnext < bufend && (c = *patnext++) != EOS) 377 *bufnext++ = (Char) c; 378 *bufnext = EOS; 379 380 bufnext = patbuf; 381 qpatnext = patbuf; 382 /* we don't need to check for buffer overflow any more */ 383 while ((c = *qpatnext++) != EOS) { 384 #ifdef DSPMBYTE 385 if (Ismbyte1(c) && *qpatnext != EOS) 386 { 387 *bufnext++ = CHAR(c); 388 *bufnext++ = CHAR(*qpatnext++); 389 } 390 else 391 #endif /* DSPMBYTE */ 392 switch (c) { 393 case LBRACKET: 394 c = *qpatnext; 395 if (c == not) 396 ++qpatnext; 397 if (*qpatnext == EOS || 398 Strchr(qpatnext + 1, RBRACKET) == NULL) { 399 *bufnext++ = LBRACKET; 400 if (c == not) 401 --qpatnext; 402 break; 403 } 404 pglob->gl_flags |= GLOB_MAGCHAR; 405 *bufnext++ = M_SET; 406 if (c == not) 407 *bufnext++ = m_not; 408 c = *qpatnext++; 409 do { 410 *bufnext++ = CHAR(c); 411 if (*qpatnext == RANGE && 412 (c = qpatnext[1]) != RBRACKET) { 413 *bufnext++ = M_RNG; 414 *bufnext++ = CHAR(c); 415 qpatnext += 2; 416 } 417 } while ((c = *qpatnext++) != RBRACKET); 418 *bufnext++ = M_END; 419 break; 420 case QUESTION: 421 pglob->gl_flags |= GLOB_MAGCHAR; 422 *bufnext++ = M_ONE; 423 break; 424 case STAR: 425 pglob->gl_flags |= GLOB_MAGCHAR; 426 /* collapse adjacent stars to one, to avoid 427 * exponential behavior 428 */ 429 if (bufnext == patbuf || bufnext[-1] != M_ALL) 430 *bufnext++ = M_ALL; 431 break; 432 default: 433 *bufnext++ = CHAR(c); 434 break; 435 } 436 } 437 *bufnext = EOS; 438 #ifdef DEBUG 439 qprintf(patbuf); 440 #endif 441 442 if ((err = glob1(patbuf, pglob, no_match)) != 0) 443 return (err); 444 445 /* 446 * If there was no match we are going to append the pattern 447 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified 448 * and the pattern did not contain any magic characters 449 * GLOB_NOMAGIC is there just for compatibility with csh. 450 */ 451 if (pglob->gl_pathc == oldpathc && 452 ((flags & GLOB_NOCHECK) || 453 ((flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR)))) { 454 if (!(flags & GLOB_QUOTE)) { 455 Char *dp = compilebuf; 456 const unsigned char *sp = compilepat; 457 458 while ((*dp++ = *sp++) != '\0') 459 continue; 460 } 461 else { 462 /* 463 * copy pattern, interpreting quotes; this is slightly different 464 * than the interpretation of quotes above -- which should prevail? 465 */ 466 while (*compilepat != EOS) { 467 if (*compilepat == QUOTE) { 468 if (*++compilepat == EOS) 469 --compilepat; 470 } 471 *compilebuf++ = (unsigned char) *compilepat++; 472 } 473 *compilebuf = EOS; 474 } 475 return (globextend(patbuf, pglob)); 476 } 477 else if (!(flags & GLOB_NOSORT) && (pglob->gl_pathc != oldpathc)) 478 qsort((char *) (pglob->gl_pathv + pglob->gl_offs + oldpathc), 479 pglob->gl_pathc - oldpathc, sizeof(char *), 480 (int (*) __P((const void *, const void *))) compare); 481 return (0); 482 } 483 484 static int 485 glob1(pattern, pglob, no_match) 486 Char *pattern; 487 glob_t *pglob; 488 int no_match; 489 { 490 Char pathbuf[GLOBBUFLEN + 1]; 491 492 /* 493 * a null pathname is invalid -- POSIX 1003.1 sect. 2.4. 494 */ 495 if (*pattern == EOS) 496 return (0); 497 return (glob2(pathbuf, pathbuf, pattern, pglob, no_match)); 498 } 499 500 /* 501 * functions glob2 and glob3 are mutually recursive; there is one level 502 * of recursion for each segment in the pattern that contains one or 503 * more meta characters. 504 */ 505 static int 506 glob2(pathbuf, pathend, pattern, pglob, no_match) 507 Char *pathbuf, *pathend, *pattern; 508 glob_t *pglob; 509 int no_match; 510 { 511 struct stat sbuf; 512 int anymeta; 513 Char *p, *q; 514 515 /* 516 * loop over pattern segments until end of pattern or until segment with 517 * meta character found. 518 */ 519 anymeta = 0; 520 for (;;) { 521 if (*pattern == EOS) { /* end of pattern? */ 522 *pathend = EOS; 523 524 if (Lstat(pathbuf, &sbuf)) 525 return (0); 526 527 if (((pglob->gl_flags & GLOB_MARK) && 528 pathend[-1] != SEP) && 529 (S_ISDIR(sbuf.st_mode) 530 #ifdef S_IFLNK 531 || (S_ISLNK(sbuf.st_mode) && 532 (Stat(pathbuf, &sbuf) == 0) && 533 S_ISDIR(sbuf.st_mode)) 534 #endif 535 )) { 536 *pathend++ = SEP; 537 *pathend = EOS; 538 } 539 ++pglob->gl_matchc; 540 return (globextend(pathbuf, pglob)); 541 } 542 543 /* find end of next segment, copy tentatively to pathend */ 544 q = pathend; 545 p = pattern; 546 while (*p != EOS && *p != SEP) { 547 if (ismeta(*p)) 548 anymeta = 1; 549 *q++ = *p++; 550 } 551 552 if (!anymeta) { /* no expansion, do next segment */ 553 pathend = q; 554 pattern = p; 555 while (*pattern == SEP) 556 *pathend++ = *pattern++; 557 } 558 else /* need expansion, recurse */ 559 return (glob3(pathbuf, pathend, pattern, p, pglob, no_match)); 560 } 561 /* NOTREACHED */ 562 } 563 564 565 static int 566 glob3(pathbuf, pathend, pattern, restpattern, pglob, no_match) 567 Char *pathbuf, *pathend, *pattern, *restpattern; 568 glob_t *pglob; 569 int no_match; 570 { 571 DIR *dirp; 572 struct dirent *dp; 573 int err; 574 Char m_not = (pglob->gl_flags & GLOB_ALTNOT) ? M_ALTNOT : M_NOT; 575 char cpathbuf[GLOBBUFLEN], *ptr;; 576 577 *pathend = EOS; 578 errno = 0; 579 580 if (!(dirp = Opendir(pathbuf))) { 581 /* todo: don't call for ENOENT or ENOTDIR? */ 582 for (ptr = cpathbuf; (*ptr++ = (char) *pathbuf++) != EOS;) 583 continue; 584 if ((pglob->gl_errfunc && (*pglob->gl_errfunc) (cpathbuf, errno)) || 585 (pglob->gl_flags & GLOB_ERR)) 586 return (GLOB_ABEND); 587 else 588 return (0); 589 } 590 591 err = 0; 592 593 /* search directory for matching names */ 594 while ((dp = readdir(dirp)) != NULL) { 595 register unsigned char *sc; 596 register Char *dc; 597 598 /* initial DOT must be matched literally */ 599 if (dp->d_name[0] == DOT && *pattern != DOT) 600 continue; 601 for (sc = (unsigned char *) dp->d_name, dc = pathend; 602 (*dc++ = *sc++) != '\0';) 603 continue; 604 if (match(pathend, pattern, restpattern, (int) m_not) == no_match) { 605 *pathend = EOS; 606 continue; 607 } 608 err = glob2(pathbuf, --dc, restpattern, pglob, no_match); 609 if (err) 610 break; 611 } 612 /* todo: check error from readdir? */ 613 (void) closedir(dirp); 614 return (err); 615 } 616 617 618 /* 619 * Extend the gl_pathv member of a glob_t structure to accomodate a new item, 620 * add the new item, and update gl_pathc. 621 * 622 * This assumes the BSD realloc, which only copies the block when its size 623 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic 624 * behavior. 625 * 626 * Return 0 if new item added, error code if memory couldn't be allocated. 627 * 628 * Invariant of the glob_t structure: 629 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and 630 * gl_pathv points to (gl_offs + gl_pathc + 1) items. 631 */ 632 static int 633 globextend(path, pglob) 634 Char *path; 635 glob_t *pglob; 636 { 637 register char **pathv; 638 register int i; 639 unsigned int newsize; 640 char *copy; 641 Char *p; 642 643 newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); 644 pathv = (char **) (pglob->gl_pathv ? 645 xrealloc((ptr_t) pglob->gl_pathv, (size_t) newsize) : 646 xmalloc((size_t) newsize)); 647 if (pathv == NULL) 648 return (GLOB_NOSPACE); 649 650 if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 651 /* first time around -- clear initial gl_offs items */ 652 pathv += pglob->gl_offs; 653 for (i = pglob->gl_offs; --i >= 0;) 654 *--pathv = NULL; 655 } 656 pglob->gl_pathv = pathv; 657 658 for (p = path; *p++;) 659 continue; 660 if ((copy = (char *) xmalloc((size_t) (p - path))) != NULL) { 661 register char *dc = copy; 662 register Char *sc = path; 663 664 while ((*dc++ = *sc++) != '\0') 665 continue; 666 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; 667 } 668 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; 669 return ((copy == NULL) ? GLOB_NOSPACE : 0); 670 } 671 672 673 /* 674 * pattern matching function for filenames. Each occurrence of the * 675 * pattern causes a recursion level. 676 */ 677 static int 678 match(name, pat, patend, m_not) 679 register Char *name, *pat, *patend; 680 int m_not; 681 { 682 int ok, negate_range; 683 Char c, k; 684 685 while (pat < patend) { 686 c = *pat++; 687 switch (c & M_MASK) { 688 case M_ALL: 689 if (pat == patend) 690 return (1); 691 do 692 if (match(name, pat, patend, m_not)) 693 return (1); 694 while (*name++ != EOS); 695 return (0); 696 case M_ONE: 697 if (*name++ == EOS) 698 return (0); 699 break; 700 case M_SET: 701 ok = 0; 702 if ((k = *name++) == EOS) 703 return (0); 704 if ((negate_range = ((*pat & M_MASK) == m_not)) != 0) 705 ++pat; 706 while (((c = *pat++) & M_MASK) != M_END) { 707 if ((*pat & M_MASK) == M_RNG) { 708 if (globcharcoll(CHAR(c), CHAR(k)) <= 0 && 709 globcharcoll(CHAR(k), CHAR(pat[1])) <= 0) 710 ok = 1; 711 pat += 2; 712 } 713 else if (c == k) 714 ok = 1; 715 } 716 if (ok == negate_range) 717 return (0); 718 break; 719 default: 720 k = *name++; 721 if (samecase(k) != samecase(c)) 722 return (0); 723 break; 724 } 725 } 726 return (*name == EOS); 727 } 728 729 /* free allocated data belonging to a glob_t structure */ 730 void 731 globfree(pglob) 732 glob_t *pglob; 733 { 734 register int i; 735 register char **pp; 736 737 if (pglob->gl_pathv != NULL) { 738 pp = pglob->gl_pathv + pglob->gl_offs; 739 for (i = pglob->gl_pathc; i--; ++pp) 740 if (*pp) 741 xfree((ptr_t) *pp), *pp = NULL; 742 xfree((ptr_t) pglob->gl_pathv), pglob->gl_pathv = NULL; 743 } 744 } 745