forsyth@minster.UUCP (forsyth) (07/30/86)
# To unbundle, sh this file echo 'catpath.3' >&2 sed 's/^-//' >catpath.3 << 'End of catpath.3' -.TH CATPATH 3 local -.SH NAME -catpath \- concatenate path name components and simplify -.SH SYNOPSIS -.nf -.B "char \(**catpath(buf, bufsiz, comps)" -.br -.B char \(**buf; -.br -.B unsigned bufsiz; -.br -.B char \(**comps[\|]; -.fi -.SH DESCRIPTION -.I Catpath -concatenates the -file name components represented by -null-terminated strings in the array -.IR comps , -which is terminated by a null pointer, -to form a complete path name -which is left in -.IR buf . -A pointer to -.I buf -is returned (but see below). -.I Buf -is taken to be -.I bufsiz -characters long, and the result must fit in that space, -including the terminating null byte. -.PP -Each element string in -the array -.I comps -can contain a portion of a path name, -including several directory components separated by `/'. -.I Catpath -will simplify the resulting path name -by removing redundant references to -.RB ` . ' -and -.RB ` .. '. -.SH SEE ALSO -basename(1), getcwd(3) -.SH DIAGNOSTICS -If -.I buf -is too small, -.I catpath -returns a null pointer and sets -the external cell -.I errno -to -ERANGE -(see -.IR intro (2)). End of catpath.3 echo 'catpath.c' >&2 sed 's/^-//' >catpath.c << 'End of catpath.c' -/* - * make the simplified pathname, of a catenation of components - * - * M C Atkins, University of York (mcvax!minster.york.ac.uk!martin) - */ -#include <errno.h> - -extern int errno; - -#define isend(cp) (*(cp) == '/' || *(cp) == '\0') -#define isdot(cp) (*(cp) == '.' && isend(cp+1)) -#define isdotdot(cp) (*(cp) == '.' && isdot(cp+1)) - -char * -catpath(buf, bufsiz, comps) -char *buf; -int bufsiz; -char *comps[]; -{ - register char *fcp; - register char *start = buf; - register char *tcp; - register char *lcp; - register char *endp = &buf[bufsiz-4]; - - if(comps[0] != 0 && comps[0][0] == '/') - *start++ = '/'; - *start = '\0'; - tcp = start; - while((fcp = comps[0]) != 0 && tcp < endp) { - while(*fcp) { - if(*fcp == '/') { - fcp++; - continue; - } - if(isdot(fcp)) { - fcp++; - continue; - } - if(isdotdot(fcp)) { - fcp += 2; - if(tcp != start) { - lcp = tcp - 2; - while(lcp > start && *lcp != '/') - lcp--; - if(lcp > start) - lcp++; - else - lcp = start; - if(!isdotdot(lcp)) { - tcp = lcp; - *tcp = '\0'; - continue; - } - } - *tcp++ = '.'; - *tcp++ = '.'; - *tcp++ = '/'; - continue; - } - while(*fcp != '\0' && *fcp != '/' && tcp < endp) - *tcp++ = *fcp++; - *tcp++ = '/'; - } - comps++; - } - if(tcp >= endp) { - errno = ERANGE; - return 0; - } - if(tcp > buf+1) - tcp[-1] = '\0'; - return buf; -} End of catpath.c