/* * Copyright (c) 1999-2003 Smithsonian Astrophysical Observatory */ /* * * Find.c -- find files via the path environment variable * (and related routines) * */ #include /* * * private routines * */ #define MAXBUFSIZE 8192 #ifndef HAVE_UNISTD_H #define F_OK 0 /* does file exist */ #define X_OK 1 /* is it executable by caller */ #define W_OK 2 /* is it writable by caller */ #define R_OK 4 /* is it readable by caller */ #endif /* not part of unistd.h but we need to differentiate directories */ #ifdef D_OK #undef D_OK #endif #define D_OK 256 /* is it a directory */ #ifdef ANSI_FUNC static int amparse (char *mode) #else static int amparse(mode) char *mode; #endif { int xmode = 0; xmode |= ( strpbrk(mode, "r") != NULL ? R_OK : 0 ); xmode |= ( strpbrk(mode, "w") != NULL ? W_OK : 0 ); xmode |= ( strpbrk(mode, "x") != NULL ? X_OK : 0 ); xmode |= ( strpbrk(mode, "f") != NULL ? F_OK : 0 ); xmode |= ( strpbrk(mode, "d") != NULL ? D_OK : 0 ); return xmode; } #ifdef ANSI_FUNC static char * findpath (char *name, char *mode, char *path) #else static char *findpath(name, mode, path) char *name; char *mode; char *path; #endif { char pathbuff[MAXBUFSIZE]; char namebuff[MAXBUFSIZE]; char tempbuff[MAXBUFSIZE]; char backmode[MAXBUFSIZE]; char *here, *found; int len; int mark = 0; int skip = strpbrk(mode, ">") != NULL; int pick = strpbrk(mode, "<") != NULL; if ( skip && pick ) return NULL; if ( (path==NULL) || ( name[0] == '.' && name[1] == '/' ) || name[0] == '/' ) return Access(name, mode); strncpy(pathbuff, path, MAXBUFSIZE-1); pathbuff[MAXBUFSIZE-1] = '\0'; path = pathbuff; if ( (here = strpbrk(pathbuff, ":;")) ) { mark = *here; *here++ = '\0'; } while ( path ) { /* if there is an environment variable ... */ if ( strchr(path, '$') ) { /* exand it */ ExpandEnv(path, tempbuff, MAXBUFSIZE); /* make sure we could expand it (otherwise we get an infinite loop) */ if( !strchr(tempbuff, '$') ){ if ( (found = findpath(name, mode, tempbuff)) ) return found; } } else { if ( !skip ) { if ( !strcmp(".", path) ) path[0] = '\0'; strncpy(namebuff, path, MAXBUFSIZE-1); namebuff[MAXBUFSIZE-1] = '\0'; len = strlen(namebuff); if ( namebuff[0] && namebuff[len-1] != '/' ){ if( (len+1) <= (MAXBUFSIZE-1) ){ strcat(namebuff, "/"); len++; } /* filename is too large, so we can't find it */ else return NULL; } if( len+strlen(name) <= MAXBUFSIZE-1 ) strcat(namebuff, name); /* filename is too large, so we can't find it */ else return NULL; if ( (found = Access(namebuff, mode)) ) return found; } } if ( mark == ';' ) { if ( skip ) { skip = 0; /* Knock down the skip mode to select all * directories in path after the first ";" */ strncpy(backmode, mode, MAXBUFSIZE-1); backmode[MAXBUFSIZE-1] = '\0'; mode = backmode; } if ( pick ) return NULL; } path = here; if ( here && (here = strpbrk(here, ":;")) ) { mark = *here; *here++ = '\0'; } } return NULL; } /* * * public routines * */ /* * * ResolvePath -- resolve the path to remove . and .. entries * */ #ifdef ANSI_FUNC char * ResolvePath (char *ibuf, char *obuf, int maxlen) #else char *ResolvePath(ibuf, obuf, maxlen) char *ibuf; char *obuf; int maxlen; #endif { char path[MAXBUFSIZE]; char *part[MAXBUFSIZE]; char *tbuf; int i, j; int len; int npart=0; /* if we have no path separators, we really don't have much to do! */ if( strchr(ibuf, '/') == NULL ){ strncpy(obuf, ibuf, maxlen-1); obuf[maxlen-1] = '\0'; return(obuf); } /* if its just "/" or "/.", its easy */ if( !strcmp(ibuf, "/") || !strcmp(ibuf, "/.") ){ strncpy(obuf, "/", maxlen-1); obuf[maxlen-1] = '\0'; return(obuf); } /* if we have a relative path to deal with, get current directory */ if( (*ibuf == '.') || ( (strchr(ibuf, '/') != NULL) && (*ibuf != '/') ) ){ getcwd(path, MAXBUFSIZE); } else{ *path = '\0'; } /* construct the total string we have to deal with */ len = strlen(path) + strlen(ibuf) + 1; tbuf = (char *)xmalloc(len+1); if( *path ){ strcpy(tbuf, path); strcat(tbuf, "/"); strcat(tbuf, ibuf); } else{ strcpy(tbuf, ibuf); } /* construct the parts array from this string, removing / characters and null-terminating each part */ for(i=0; i=0; j--){ if( part[j] ){ part[j] = NULL; break; } } } } /* construct a new string from the remaining parts */ *obuf = '\0'; len = 0; for(i=0; i