#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <fcntl.h>
#include <string.h>
#include <debug.h>
#include <conv.h>
#include "_rtld.h"
#include "msg.h"
void
set_dirs(Alist **alpp, Spath_defn *sdp, uint_t flags)
{
while (sdp->sd_name) {
Pdesc *pdp;
if ((pdp = alist_append(alpp, NULL, sizeof (Pdesc),
AL_CNT_SPATH)) == NULL)
return;
pdp->pd_pname = (char *)sdp->sd_name;
pdp->pd_plen = sdp->sd_len;
pdp->pd_flags = flags;
sdp++;
}
}
static void
print_default_dirs(Lm_list *lml, Alist *alp, int search)
{
uint_t flags = 0;
int num = 0;
Aliste idx;
Pdesc *pdp;
if (search)
(void) printf(MSG_INTL(MSG_LDD_PTH_BGNDFL));
for (ALIST_TRAVERSE(alp, idx, pdp)) {
flags = pdp->pd_flags;
if (search) {
const char *fmt;
if (num++)
fmt = MSG_ORIG(MSG_LDD_FMT_PATHN);
else
fmt = MSG_ORIG(MSG_LDD_FMT_PATH1);
(void) printf(fmt, pdp->pd_pname);
} else
DBG_CALL(Dbg_libs_path(lml, pdp->pd_pname,
pdp->pd_flags, config->c_name));
}
if (search) {
if (flags & LA_SER_CONFIG)
(void) printf(MSG_INTL(MSG_LDD_PTH_ENDDFLC),
config->c_name);
else
(void) printf(MSG_INTL(MSG_LDD_PTH_ENDDFL));
}
}
static Alist **
get_dir_list(uchar_t rules, Rt_map *lmp, uint_t flags)
{
Alist **dalpp = NULL;
Lm_list *lml = LIST(lmp);
int search;
if ((lml->lm_flags & LML_FLG_TRC_SEARCH) &&
((FLAGS1(lmp) & FL1_RT_LDDSTUB) == 0) &&
((flags & FLG_RT_AUDIT) == 0))
search = 1;
else
search = 0;
switch (rules) {
case RPLENV:
if (rpl_libpath) {
uint_t mode = (LA_SER_LIBPATH | PD_FLG_UNIQUE);
if (env_info & ENV_INF_PATHCFG)
mode |= LA_SER_CONFIG;
DBG_CALL(Dbg_libs_path(lml, rpl_libpath, mode,
config->c_name));
if (search) {
const char *fmt;
if (env_info & ENV_INF_PATHCFG)
fmt = MSG_INTL(MSG_LDD_PTH_LIBPATHC);
else
fmt = MSG_INTL(MSG_LDD_PTH_LIBPATH);
(void) printf(fmt, rpl_libpath, config->c_name);
}
if (rpl_libdirs && (rtld_flags & RT_FL_SECURE) &&
(search || DBG_ENABLED))
remove_alist(&rpl_libdirs, 1);
if (rpl_libdirs == NULL) {
(void) expand_paths(lmp, rpl_libpath,
&rpl_libdirs, AL_CNT_SEARCH, mode,
PD_TKN_CAP);
}
dalpp = &rpl_libdirs;
}
break;
case PRMENV:
if (prm_libpath) {
uint_t mode =
(LA_SER_LIBPATH | LA_SER_CONFIG | PD_FLG_UNIQUE);
DBG_CALL(Dbg_libs_path(lml, prm_libpath, mode,
config->c_name));
if (search)
(void) printf(MSG_INTL(MSG_LDD_PTH_LIBPATHC),
prm_libpath, config->c_name);
if (prm_libdirs && (rtld_flags & RT_FL_SECURE) &&
(search || DBG_ENABLED))
remove_alist(&prm_libdirs, 1);
if (prm_libdirs == NULL) {
(void) expand_paths(lmp, prm_libpath,
&prm_libdirs, AL_CNT_SEARCH, mode,
PD_TKN_CAP);
}
dalpp = &prm_libdirs;
}
break;
case RUNPATH:
if (RPATH(lmp)) {
DBG_CALL(Dbg_libs_path(lml, RPATH(lmp), LA_SER_RUNPATH,
NAME(lmp)));
if (search)
(void) printf(MSG_INTL(MSG_LDD_PTH_RUNPATH),
RPATH(lmp), NAME(lmp));
if (RLIST(lmp) && (rtld_flags & RT_FL_SECURE) &&
(search || DBG_ENABLED))
remove_alist(&RLIST(lmp), 1);
if (RLIST(lmp) == NULL) {
(void) expand_paths(lmp, RPATH(lmp),
&RLIST(lmp), AL_CNT_SEARCH, LA_SER_RUNPATH,
PD_TKN_CAP);
}
dalpp = &RLIST(lmp);
}
break;
case DEFAULT:
if ((FLAGS1(lmp) & FL1_RT_NODEFLIB) == 0) {
if ((rtld_flags & RT_FL_SECURE) &&
((flags & FLG_RT_PRELOAD) ||
((flags & FLG_RT_AUDIT) && !(FLAGS1(lmp) &
FL1_RT_DEPAUD))))
dalpp = LM_SECURE_DIRS(lmp)();
else
dalpp = LM_DEFAULT_DIRS(lmp)();
}
if (dalpp && (search || DBG_ENABLED))
print_default_dirs(lml, *dalpp, search);
break;
default:
break;
}
return (dalpp);
}
Pdesc *
get_next_dir(Spath_desc *sdp, Rt_map *lmp, uint_t flags)
{
while (*sdp->sp_rule) {
Alist *alp;
if ((sdp->sp_dalpp || ((sdp->sp_dalpp =
get_dir_list(*sdp->sp_rule, lmp, flags)) != NULL)) &&
((alp = *sdp->sp_dalpp) != NULL) &&
(alist_nitems(alp) > sdp->sp_idx)) {
return (alist_item(alp, sdp->sp_idx++));
}
sdp->sp_rule++;
sdp->sp_dalpp = NULL;
sdp->sp_idx = 0;
}
return (NULL);
}
uint_t
expand(char **name, size_t *len, char **list, uint_t orig, uint_t omit,
Rt_map *lmp)
{
char _name[PATH_MAX];
char *token = NULL, *oname, *ename, *optr, *_optr, *nptr, *_list;
size_t olen = 0, nlen = 0, _len;
int isaflag = 0;
uint_t flags = 0;
Lm_list *lml = LIST(lmp);
optr = _optr = oname = ename = *name;
ename += *len;
nptr = _name;
while ((olen < *len) && (nlen < PATH_MAX)) {
uint_t _flags;
if ((*optr != '$') || ((olen - *len) == 1)) {
if ((rtld_flags & RT_FL_DIRCFG) &&
(orig & LA_SER_MASK) && (*optr == '/') &&
(optr != oname) && (*(optr - 1) == '.'))
flags |= TKN_DOTSLASH;
olen++, optr++;
continue;
}
if ((_len = (optr - _optr)) != 0) {
if ((nlen += _len) < PATH_MAX) {
(void) strncpy(nptr, _optr, _len);
nptr = nptr + _len;
} else {
eprintf(lml, ERR_FATAL,
MSG_INTL(MSG_ERR_EXPAND1), NAME(lmp),
oname);
return (0);
}
}
olen++, optr++;
_flags = 0;
token = 0;
if (strncmp(optr, MSG_ORIG(MSG_TKN_ORIGIN),
MSG_TKN_ORIGIN_SIZE) == 0) {
token = (char *)MSG_ORIG(MSG_TKN_ORIGIN);
if (((omit & PD_TKN_ORIGIN) == 0) &&
(((_len = DIRSZ(lmp)) != 0) ||
((_len = fullpath(lmp, 0)) != 0))) {
if ((nlen += _len) < PATH_MAX) {
(void) strncpy(nptr,
ORIGNAME(lmp), _len);
nptr = nptr +_len;
olen += MSG_TKN_ORIGIN_SIZE;
optr += MSG_TKN_ORIGIN_SIZE;
_flags |= PD_TKN_ORIGIN;
} else {
eprintf(lml, ERR_FATAL,
MSG_INTL(MSG_ERR_EXPAND1),
NAME(lmp), oname);
return (0);
}
}
} else if (strncmp(optr, MSG_ORIG(MSG_TKN_PLATFORM),
MSG_TKN_PLATFORM_SIZE) == 0) {
Syscapset *scapset;
if (FLAGS1(lmp) & FL1_RT_ALTCAP)
scapset = alt_scapset;
else
scapset = org_scapset;
token = (char *)MSG_ORIG(MSG_TKN_PLATFORM);
if (((omit & PD_TKN_PLATFORM) == 0) &&
((scapset->sc_plat == NULL) &&
(scapset->sc_platsz == 0)))
platform_name(scapset);
if (((omit & PD_TKN_PLATFORM) == 0) &&
scapset->sc_plat) {
nlen += scapset->sc_platsz;
if (nlen < PATH_MAX) {
(void) strncpy(nptr, scapset->sc_plat,
scapset->sc_platsz);
nptr = nptr + scapset->sc_platsz;
olen += MSG_TKN_PLATFORM_SIZE;
optr += MSG_TKN_PLATFORM_SIZE;
_flags |= PD_TKN_PLATFORM;
} else {
eprintf(lml, ERR_FATAL,
MSG_INTL(MSG_ERR_EXPAND1),
NAME(lmp), oname);
return (0);
}
}
} else if (strncmp(optr, MSG_ORIG(MSG_TKN_MACHINE),
MSG_TKN_MACHINE_SIZE) == 0) {
Syscapset *scapset;
if (FLAGS1(lmp) & FL1_RT_ALTCAP)
scapset = alt_scapset;
else
scapset = org_scapset;
token = (char *)MSG_ORIG(MSG_TKN_MACHINE);
if (((omit & PD_TKN_MACHINE) == 0) &&
((scapset->sc_mach == NULL) &&
(scapset->sc_machsz == 0)))
machine_name(scapset);
if (((omit & PD_TKN_MACHINE) == 0) &&
scapset->sc_mach) {
nlen += scapset->sc_machsz;
if (nlen < PATH_MAX) {
(void) strncpy(nptr, scapset->sc_mach,
scapset->sc_machsz);
nptr = nptr + scapset->sc_machsz;
olen += MSG_TKN_MACHINE_SIZE;
optr += MSG_TKN_MACHINE_SIZE;
_flags |= PD_TKN_MACHINE;
} else {
eprintf(lml, ERR_FATAL,
MSG_INTL(MSG_ERR_EXPAND1),
NAME(lmp), oname);
return (0);
}
}
} else if (strncmp(optr, MSG_ORIG(MSG_TKN_OSNAME),
MSG_TKN_OSNAME_SIZE) == 0) {
token = (char *)MSG_ORIG(MSG_TKN_OSNAME);
if (((omit & PD_TKN_OSNAME) == 0) && (uts == NULL))
uts = conv_uts();
if (((omit & PD_TKN_OSNAME) == 0) &&
(uts && uts->uts_osnamesz)) {
if ((nlen += uts->uts_osnamesz) < PATH_MAX) {
(void) strncpy(nptr, uts->uts_osname,
uts->uts_osnamesz);
nptr = nptr + uts->uts_osnamesz;
olen += MSG_TKN_OSNAME_SIZE;
optr += MSG_TKN_OSNAME_SIZE;
_flags |= PD_TKN_OSNAME;
} else {
eprintf(lml, ERR_FATAL,
MSG_INTL(MSG_ERR_EXPAND1),
NAME(lmp), oname);
return (0);
}
}
} else if (strncmp(optr, MSG_ORIG(MSG_TKN_OSREL),
MSG_TKN_OSREL_SIZE) == 0) {
token = (char *)MSG_ORIG(MSG_TKN_OSREL);
if (((omit & PD_TKN_OSREL) == 0) && (uts == 0))
uts = conv_uts();
if (((omit & PD_TKN_OSREL) == 0) &&
(uts && uts->uts_osrelsz)) {
if ((nlen += uts->uts_osrelsz) < PATH_MAX) {
(void) strncpy(nptr, uts->uts_osrel,
uts->uts_osrelsz);
nptr = nptr + uts->uts_osrelsz;
olen += MSG_TKN_OSREL_SIZE;
optr += MSG_TKN_OSREL_SIZE;
_flags |= PD_TKN_OSREL;
} else {
eprintf(lml, ERR_FATAL,
MSG_INTL(MSG_ERR_EXPAND1),
NAME(lmp), oname);
return (0);
}
}
} else if ((strncmp(optr, MSG_ORIG(MSG_TKN_ISALIST),
MSG_TKN_ISALIST_SIZE) == 0)) {
int ok;
token = (char *)MSG_ORIG(MSG_TKN_ISALIST);
if ((omit & PD_TKN_ISALIST) || isaflag++)
ok = 0;
else
ok = 1;
if (ok && (isa == NULL))
isa = conv_isalist();
if (ok && isa && isa->isa_listsz) {
size_t no, mlen, tlen, hlen = olen - 1;
char *lptr;
Isa_opt *opt = isa->isa_opt;
if ((nlen += opt->isa_namesz) < PATH_MAX) {
(void) strncpy(nptr, opt->isa_name,
opt->isa_namesz);
nptr = nptr + opt->isa_namesz;
olen += MSG_TKN_ISALIST_SIZE;
optr += MSG_TKN_ISALIST_SIZE;
_flags |= PD_TKN_ISALIST;
} else {
eprintf(lml, ERR_FATAL,
MSG_INTL(MSG_ERR_EXPAND1),
NAME(lmp), oname);
return (0);
}
if (list) {
tlen = *len - olen;
mlen = ((hlen + tlen) *
(isa->isa_optno - 1)) +
isa->isa_listsz - opt->isa_namesz +
strlen(*list);
if ((_list = lptr =
malloc(mlen)) == NULL)
return (0);
for (no = 1, opt++; no < isa->isa_optno;
no++, opt++) {
(void) strncpy(lptr, *name,
hlen);
lptr = lptr + hlen;
(void) strncpy(lptr,
opt->isa_name,
opt->isa_namesz);
lptr = lptr + opt->isa_namesz;
(void) strncpy(lptr, optr,
tlen);
lptr = lptr + tlen;
*lptr++ = ':';
}
if (**list)
(void) strcpy(lptr, *list);
else
*--lptr = '\0';
}
}
} else if (strncmp(optr, MSG_ORIG(MSG_TKN_CAPABILITY),
MSG_TKN_CAPABILITY_SIZE) == 0) {
char *bptr = nptr - 1;
char *eptr = optr + MSG_TKN_CAPABILITY_SIZE;
token = (char *)MSG_ORIG(MSG_TKN_CAPABILITY);
if (((omit & PD_TKN_CAP) == 0) &&
((bptr > _name) && (*bptr == '/') &&
((*eptr == '\0') || (*eptr == ':')))) {
nptr--, nlen--;
olen += MSG_TKN_CAPABILITY_SIZE;
optr += MSG_TKN_CAPABILITY_SIZE;
_flags |= PD_TKN_CAP;
}
} else if (strncmp(optr, MSG_ORIG(MSG_TKN_HWCAP),
MSG_TKN_HWCAP_SIZE) == 0) {
char *bptr = nptr - 1;
char *eptr = optr + MSG_TKN_HWCAP_SIZE;
token = (char *)MSG_ORIG(MSG_TKN_HWCAP);
if (((omit & PD_TKN_CAP) == 0) &&
(rtld_flags2 & RT_FL2_HWCAP) &&
((bptr > _name) && (*bptr == '/') &&
((*eptr == '\0') || (*eptr == ':')))) {
nptr--, nlen--;
olen += MSG_TKN_HWCAP_SIZE;
optr += MSG_TKN_HWCAP_SIZE;
_flags |= PD_TKN_CAP;
}
} else {
*nptr++ = '$';
nlen++;
}
if (token) {
if (_flags)
flags |= _flags;
else {
char buf[PATH_MAX], *str;
str = strchr(oname, ':');
if (str != NULL) {
size_t slen = str - oname;
(void) strncpy(buf, oname, slen);
buf[slen] = '\0';
str = buf;
} else
str = oname;
eprintf(lml, ERR_FATAL,
MSG_INTL(MSG_ERR_EXPAND2), NAME(lmp),
str, token);
return (0);
}
}
_optr = optr;
}
if (nlen >= PATH_MAX) {
eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ERR_EXPAND1), NAME(lmp),
oname);
return (0);
}
if (isa && isaflag) {
if (isaflag == 1) {
if (list)
*list = _list;
} else {
flags &= ~PD_TKN_ISALIST;
if ((nptr = (char *)stravl_insert(*name, 0,
(*len + 1), 1)) == NULL)
return (0);
*name = nptr;
return (TKN_NONE);
}
}
if ((_len = (optr - _optr)) != 0) {
if ((nlen += _len) < PATH_MAX) {
(void) strncpy(nptr, _optr, _len);
nptr = nptr + _len;
} else {
eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ERR_EXPAND1),
NAME(lmp), oname);
return (0);
}
}
*nptr = '\0';
if (list && (rtld_flags & RT_FL_DIRCFG) && (flags & TKN_DOTSLASH)) {
int len;
if ((len = resolvepath(_name, _name, (PATH_MAX - 1))) >= 0) {
nlen = (size_t)len;
_name[nlen] = '\0';
flags |= PD_TKN_RESOLVED;
}
}
if ((nptr = (char *)stravl_insert(_name, 0, (nlen + 1), 1)) == NULL)
return (0);
*name = nptr;
*len = nlen;
return (flags ? flags : TKN_NONE);
}
int
is_path_secure(char *opath, Rt_map *clmp, uint_t info, uint_t flags)
{
Alist **salpp;
Aliste idx;
char buffer[PATH_MAX], *npath = NULL;
Lm_list *lml = LIST(clmp);
Pdesc *pdp;
if (info & LA_SER_CONFIG)
return (1);
if ((info & LA_SER_MASK) == 0) {
char *str;
str = strrchr(opath, '/');
if ((((str == 0) && ((info & PD_FLG_FULLPATH) == 0)) ||
((*opath == '/') && (str != opath) &&
((info & PD_FLG_EXTLOAD) == 0))) &&
((flags & PD_TKN_ORIGIN) == 0))
return (1);
if (str) {
if (str == opath)
npath = (char *)MSG_ORIG(MSG_STR_SLASH);
else {
size_t size;
if ((size = str - opath) >= PATH_MAX)
return (0);
(void) strncpy(buffer, opath, size);
buffer[size] = '\0';
npath = buffer;
}
if ((flags & PD_TKN_ORIGIN) &&
pnavl_recorded(&spavl, npath, 0, NULL)) {
DBG_CALL(Dbg_libs_insecure(lml, npath, 1));
return (1);
}
}
} else {
if (((info & LA_SER_LIBPATH) == 0) && (*opath == '/') &&
((flags & PD_TKN_ORIGIN) == 0))
return (1);
if (flags & PD_TKN_ORIGIN) {
if ((lml->lm_flags & LML_FLG_RTLDLM) &&
is_rtld_setuid())
return (1);
else if (pnavl_recorded(&spavl, opath, 0, NULL)) {
DBG_CALL(Dbg_libs_insecure(lml, opath, 1));
return (1);
}
}
npath = (char *)opath;
}
if (npath) {
salpp = LM_SECURE_DIRS(LIST(clmp)->lm_head)();
for (ALIST_TRAVERSE(*salpp, idx, pdp)) {
if (strcmp(npath, pdp->pd_pname) == 0)
return (1);
}
}
if (info & PD_FLG_EXTLOAD) {
if (lml->lm_flags & LML_FLG_TRC_ENABLE) {
if ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)
(void) printf(MSG_INTL(MSG_LDD_FIL_ILLEGAL),
opath);
} else
eprintf(lml, ERR_WARNING, MSG_INTL(MSG_SEC_ILLEGAL),
opath);
return (0);
}
if ((info & LA_SER_MASK) == 0) {
if (lml->lm_flags & LML_FLG_TRC_ENABLE) {
if ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0) {
if (lml->lm_flags &
(LML_FLG_TRC_VERBOSE | LML_FLG_TRC_SEARCH))
(void) printf(
MSG_INTL(MSG_LDD_FIL_FIND),
opath, NAME(clmp));
if (((rtld_flags & RT_FL_SILENCERR) == 0) ||
(lml->lm_flags & LML_FLG_TRC_VERBOSE))
(void) printf(
MSG_INTL(MSG_LDD_FIL_ILLEGAL),
opath);
}
} else
eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), opath,
strerror(EACCES));
} else {
DBG_CALL(Dbg_libs_insecure(lml, opath, 0));
if ((lml->lm_flags & LML_FLG_TRC_SEARCH) &&
((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0))
(void) printf(MSG_INTL(MSG_LDD_PTH_IGNORE), opath);
}
return (0);
}
inline static uint_t
is_path_unique(Alist *alp, const char *path)
{
Aliste idx;
Pdesc *pdp;
for (ALIST_TRAVERSE(alp, idx, pdp)) {
if (pdp->pd_plen && (strcmp(pdp->pd_pname, path) == 0))
return (PD_FLG_DUPLICAT);
}
return (0);
}
int
expand_paths(Rt_map *clmp, const char *list, Alist **alpp, Aliste alni,
uint_t orig, uint_t omit)
{
char *str, *olist = 0, *nlist = (char *)list;
int fnull = FALSE;
Pdesc *pdp = NULL;
for (str = nlist; *nlist || fnull; str = nlist) {
char *ostr;
char *elist = NULL;
size_t len, olen;
uint_t tkns = 0;
if (*nlist == ';')
++nlist, ++str;
if ((*nlist == ':') || fnull) {
fnull = !(fnull || *(nlist + 1));
if (*nlist)
nlist++;
if (!(orig & (LA_SER_LIBPATH | LA_SER_RUNPATH)))
continue;
str = (char *)MSG_ORIG(MSG_FMT_CWD);
len = MSG_FMT_CWD_SIZE;
} else {
uint_t _tkns;
len = 0;
while (*nlist && (*nlist != ':') && (*nlist != ';')) {
if (*nlist == '/')
tkns |= PD_FLG_PNSLASH;
nlist++, len++;
}
fnull = (*nlist == ':') && !*(nlist + 1);
if (*nlist)
nlist++;
elist = nlist;
ostr = str;
olen = len;
if ((_tkns = expand(&str, &len, &elist, orig, omit,
clmp)) == 0)
continue;
tkns |= _tkns;
}
if ((rtld_flags & RT_FL_SECURE) &&
(is_path_secure(str, clmp, orig, tkns) == 0))
continue;
if (orig & PD_FLG_UNIQUE) {
Word tracing;
tracing = LIST(clmp)->lm_flags &
(LML_FLG_TRC_UNREF | LML_FLG_TRC_UNUSED);
tkns |= is_path_unique(*alpp, str);
if ((tkns & PD_FLG_DUPLICAT) && (tracing == 0) &&
(rpl_debug == 0) && (prm_debug == 0))
continue;
}
if ((pdp = alist_append(alpp, NULL, sizeof (Pdesc),
alni)) == NULL)
return (0);
pdp->pd_pname = str;
pdp->pd_plen = len;
pdp->pd_flags = (orig & LA_SER_MASK) | (tkns & PD_MSK_INHERIT);
if ((tkns & PD_MSK_EXPAND) && ((pdp->pd_oname =
stravl_insert(ostr, 0, (olen + 1), 1)) == NULL))
return (0);
if (elist && (elist != nlist)) {
if (olist)
free(olist);
nlist = olist = elist;
}
}
if (olist)
free(olist);
return (pdp != NULL);
}
size_t
fullpath(Rt_map *lmp, Fdesc *fdp)
{
const char *name;
if (fdp && (fdp->fd_flags & FLG_FD_RESOLVED)) {
if (fdp->fd_pname)
PATHNAME(lmp) = fdp->fd_pname;
else
PATHNAME(lmp) = NAME(lmp);
} else {
char _path[PATH_MAX];
const char *path;
int size, rsize;
if (fdp && fdp->fd_pname)
PATHNAME(lmp) = fdp->fd_pname;
else
PATHNAME(lmp) = NAME(lmp);
name = path = PATHNAME(lmp);
size = strlen(name);
if (path[0] != '/') {
if (getcwd(_path, (PATH_MAX - 2 - size)) != NULL) {
(void) strcat(_path, MSG_ORIG(MSG_STR_SLASH));
(void) strcat(_path, name);
path = _path;
size = strlen(path);
}
}
if ((rsize = resolvepath(path, _path, (PATH_MAX - 1))) > 0) {
_path[rsize] = '\0';
path = _path;
size = rsize;
}
if ((PATHNAME(lmp) =
stravl_insert(path, 0, (size + 1), 0)) == NULL)
PATHNAME(lmp) = name;
}
name = ORIGNAME(lmp) = PATHNAME(lmp);
DIRSZ(lmp) = strrchr(name, '/') - name;
return (DIRSZ(lmp));
}