Consider OS/2-style path
OS/2 uses 'x:' as a drive prefix and '\' as a directory separator.
This commit is contained in:
parent
a03cf65602
commit
759b6ec59f
18
edit.c
18
edit.c
@ -247,7 +247,7 @@ x_print_expansions(int nwords, char * const *words, bool is_command)
|
||||
break;
|
||||
/* All in same directory? */
|
||||
if (i == nwords) {
|
||||
while (prefix_len > 0 && words[0][prefix_len - 1] != '/')
|
||||
while (prefix_len > 0 && !IS_DIR_SEP(words[0][prefix_len - 1]))
|
||||
prefix_len--;
|
||||
use_copy = true;
|
||||
XPinit(l, nwords + 1);
|
||||
@ -323,7 +323,7 @@ x_glob_hlp_tilde_and_rem_qchar(char *s, bool magic_flag)
|
||||
* and if so, discern "~foo/bar" and "~/baz" from "~blah";
|
||||
* if we have a directory part (the former), try to expand
|
||||
*/
|
||||
if (*s == '~' && (cp = strchr(s, '/')) != NULL) {
|
||||
if (*s == '~' && (cp = ksh_strchr_dirsep(s)) != NULL) {
|
||||
/* ok, so split into "~foo"/"bar" or "~"/"baz" */
|
||||
*cp++ = 0;
|
||||
/* try to expand the tilde */
|
||||
@ -573,7 +573,7 @@ x_locate_word(const char *buf, int buflen, int pos, int *startp,
|
||||
* like file globbing.
|
||||
*/
|
||||
for (p = start; p < end; p++)
|
||||
if (buf[p] == '/')
|
||||
if (IS_DIR_SEP(buf[p]))
|
||||
break;
|
||||
iscmd = p == end;
|
||||
}
|
||||
@ -637,7 +637,7 @@ x_cf_glob(int *flagsp, const char *buf, int buflen, int pos, int *startp,
|
||||
}
|
||||
}
|
||||
|
||||
if (*toglob == '~' && !vstrchr(toglob, '/')) {
|
||||
if (*toglob == '~' && !ksh_vstrchr_dirsep(toglob)) {
|
||||
/* neither for '~foo' (but '~foo/bar') */
|
||||
*flagsp |= XCF_IS_NOSPACE;
|
||||
goto dont_add_glob;
|
||||
@ -727,11 +727,11 @@ x_basename(const char *s, const char *se)
|
||||
return (0);
|
||||
|
||||
/* Skip trailing slashes */
|
||||
for (p = se - 1; p > s && *p == '/'; p--)
|
||||
for (p = se - 1; p > s && IS_DIR_SEP(*p); p--)
|
||||
;
|
||||
for (; p > s && *p != '/'; p--)
|
||||
for (; p > s && !IS_DIR_SEP(*p); p--)
|
||||
;
|
||||
if (*p == '/' && p + 1 < se)
|
||||
if (IS_DIR_SEP(*p) && p + 1 < se)
|
||||
p++;
|
||||
|
||||
return (p - s);
|
||||
@ -2768,7 +2768,7 @@ do_complete(
|
||||
* append a space if this is a single non-directory match
|
||||
* and not a parameter or homedir substitution
|
||||
*/
|
||||
if (nwords == 1 && words[0][nlen - 1] != '/' &&
|
||||
if (nwords == 1 && !IS_DIR_SEP(words[0][nlen - 1]) &&
|
||||
!(flags & XCF_IS_NOSPACE)) {
|
||||
x_ins(" ");
|
||||
}
|
||||
@ -5381,7 +5381,7 @@ complete_word(int cmd, int count)
|
||||
* append a space if this is a non-directory match
|
||||
* and not a parameter or homedir substitution
|
||||
*/
|
||||
if (match_len > 0 && match[match_len - 1] != '/' &&
|
||||
if (match_len > 0 && !IS_DIR_SEP(match[match_len - 1]) &&
|
||||
!(flags & XCF_IS_NOSPACE))
|
||||
rval = putbuf(" ", 1, false);
|
||||
}
|
||||
|
10
eval.c
10
eval.c
@ -1542,7 +1542,7 @@ globit(XString *xs, /* dest string */
|
||||
* SunOS 4.1.3 does this...
|
||||
*/
|
||||
if ((check & GF_EXCHECK) && xp > Xstring(*xs, xp) &&
|
||||
xp[-1] == '/' && !S_ISDIR(lstatb.st_mode) &&
|
||||
IS_DIR_SEP(xp[-1]) && !S_ISDIR(lstatb.st_mode) &&
|
||||
(!S_ISLNK(lstatb.st_mode) ||
|
||||
stat_check() < 0 || !S_ISDIR(statb.st_mode)))
|
||||
return;
|
||||
@ -1552,7 +1552,7 @@ globit(XString *xs, /* dest string */
|
||||
* directory
|
||||
*/
|
||||
if (((check & GF_MARKDIR) && (check & GF_GLOBBED)) &&
|
||||
xp > Xstring(*xs, xp) && xp[-1] != '/' &&
|
||||
xp > Xstring(*xs, xp) && !IS_DIR_SEP(xp[-1]) &&
|
||||
(S_ISDIR(lstatb.st_mode) ||
|
||||
(S_ISLNK(lstatb.st_mode) && stat_check() > 0 &&
|
||||
S_ISDIR(statb.st_mode)))) {
|
||||
@ -1567,11 +1567,11 @@ globit(XString *xs, /* dest string */
|
||||
|
||||
if (xp > Xstring(*xs, xp))
|
||||
*xp++ = '/';
|
||||
while (*sp == '/') {
|
||||
while (IS_DIR_SEP(*sp)) {
|
||||
Xcheck(*xs, xp);
|
||||
*xp++ = *sp++;
|
||||
}
|
||||
np = strchr(sp, '/');
|
||||
np = ksh_strchr_dirsep(sp);
|
||||
if (np != NULL) {
|
||||
se = np;
|
||||
/* don't assume '/', can be multiple kinds */
|
||||
@ -1679,7 +1679,7 @@ maybe_expand_tilde(const char *p, XString *dsp, char **dpp, bool isassign)
|
||||
|
||||
Xinit(ts, tp, 16, ATEMP);
|
||||
/* : only for DOASNTILDE form */
|
||||
while (p[0] == CHAR && p[1] != '/' && (!isassign || p[1] != ':'))
|
||||
while (p[0] == CHAR && !IS_DIR_SEP(p[1]) && (!isassign || p[1] != ':'))
|
||||
{
|
||||
Xcheck(ts, tp);
|
||||
*tp++ = p[1];
|
||||
|
8
exec.c
8
exec.c
@ -693,7 +693,7 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
rv = subst_exstat;
|
||||
goto Leave;
|
||||
} else if (!tp) {
|
||||
if (Flag(FRESTRICTED) && vstrchr(cp, '/')) {
|
||||
if (Flag(FRESTRICTED) && ksh_vstrchr_dirsep(cp)) {
|
||||
warningf(true, "%s: %s", cp, "restricted");
|
||||
rv = 1;
|
||||
goto Leave;
|
||||
@ -1125,7 +1125,7 @@ findcom(const char *name, int flags)
|
||||
char *fpath;
|
||||
union mksh_cchack npath;
|
||||
|
||||
if (vstrchr(name, '/')) {
|
||||
if (ksh_vstrchr_dirsep(name)) {
|
||||
insert = 0;
|
||||
/* prevent FPATH search below */
|
||||
flags &= ~FC_FUNC;
|
||||
@ -1216,7 +1216,7 @@ flushcom(bool all)
|
||||
struct tstate ts;
|
||||
|
||||
for (ktwalk(&ts, &taliases); (tp = ktnext(&ts)) != NULL; )
|
||||
if ((tp->flag&ISSET) && (all || tp->val.s[0] != '/')) {
|
||||
if ((tp->flag&ISSET) && (all || !IS_ABS_PATH(tp->val.s))) {
|
||||
if (tp->flag&ALLOC) {
|
||||
tp->flag &= ~(ALLOC|ISSET);
|
||||
afree(tp->val.s, APERM);
|
||||
@ -1272,7 +1272,7 @@ search_path(const char *name, const char *lpath,
|
||||
size_t namelen;
|
||||
int ec = 0, ev;
|
||||
|
||||
if (vstrchr(name, '/')) {
|
||||
if (ksh_vstrchr_dirsep(name)) {
|
||||
if ((ec = search_access(name, mode)) == 0) {
|
||||
search_path_ok:
|
||||
if (errnop)
|
||||
|
6
main.c
6
main.c
@ -219,7 +219,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
|
||||
ccp = kshname;
|
||||
goto begin_parse_kshname;
|
||||
while ((i = ccp[argi++])) {
|
||||
if (i == '/') {
|
||||
if (IS_DIR_SEP(i)) {
|
||||
ccp += argi;
|
||||
begin_parse_kshname:
|
||||
argi = 0;
|
||||
@ -361,7 +361,7 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
|
||||
vp = global("PWD");
|
||||
cp = str_val(vp);
|
||||
/* Try to use existing $PWD if it is valid */
|
||||
set_current_wd((cp[0] == '/' && test_eval(NULL, TO_FILEQ, cp, ".",
|
||||
set_current_wd((IS_ABS_PATH(cp) && test_eval(NULL, TO_FILEQ, cp, ".",
|
||||
true)) ? cp : NULL);
|
||||
if (current_wd[0])
|
||||
simplify_path(current_wd);
|
||||
@ -1363,7 +1363,7 @@ initio(void)
|
||||
shf_fdopen(2, SHF_WR, shl_xtrace);
|
||||
#ifdef DF
|
||||
if ((lfp = getenv("SDMKSH_PATH")) == NULL) {
|
||||
if ((lfp = getenv("HOME")) == NULL || *lfp != '/')
|
||||
if ((lfp = getenv("HOME")) == NULL || !IS_ABS_PATH(lfp))
|
||||
errorf("cannot get home directory");
|
||||
lfp = shf_smprintf("%s/mksh-dbg.txt", lfp);
|
||||
}
|
||||
|
45
misc.c
45
misc.c
@ -388,7 +388,7 @@ parse_args(const char **argv,
|
||||
*/
|
||||
if (*p != '-')
|
||||
for (q = p; *q; )
|
||||
if (*q++ == '/')
|
||||
if (IS_DIR_SEP(*q++))
|
||||
p = q;
|
||||
Flag(FLOGIN) = (*p == '-');
|
||||
opts = cmd_opts;
|
||||
@ -1418,12 +1418,12 @@ do_realpath(const char *upath)
|
||||
/* max. recursion depth */
|
||||
int symlinks = 32;
|
||||
|
||||
if (upath[0] == '/') {
|
||||
if (IS_ABS_PATH(upath)) {
|
||||
/* upath is an absolute pathname */
|
||||
strdupx(ipath, upath, ATEMP);
|
||||
} else {
|
||||
/* upath is a relative pathname, prepend cwd */
|
||||
if ((tp = ksh_get_wd()) == NULL || tp[0] != '/')
|
||||
if ((tp = ksh_get_wd()) == NULL || !IS_ABS_PATH(tp))
|
||||
return (NULL);
|
||||
ipath = shf_smprintf("%s%s%s", tp, "/", upath);
|
||||
afree(tp, ATEMP);
|
||||
@ -1437,14 +1437,14 @@ do_realpath(const char *upath)
|
||||
|
||||
while (*ip) {
|
||||
/* skip slashes in input */
|
||||
while (*ip == '/')
|
||||
while (IS_DIR_SEP(*ip))
|
||||
++ip;
|
||||
if (!*ip)
|
||||
break;
|
||||
|
||||
/* get next pathname component from input */
|
||||
tp = ip;
|
||||
while (*ip && *ip != '/')
|
||||
while (*ip && !IS_DIR_SEP(*ip))
|
||||
++ip;
|
||||
len = ip - tp;
|
||||
|
||||
@ -1456,7 +1456,7 @@ do_realpath(const char *upath)
|
||||
else if (len == 2 && tp[1] == '.') {
|
||||
/* strip off last pathname component */
|
||||
while (xp > Xstring(xs, xp))
|
||||
if (*--xp == '/')
|
||||
if (IS_DIR_SEP(*--xp))
|
||||
break;
|
||||
/* then continue with the next one */
|
||||
continue;
|
||||
@ -1479,7 +1479,7 @@ do_realpath(const char *upath)
|
||||
/* lstat failed */
|
||||
if (errno == ENOENT) {
|
||||
/* because the pathname does not exist */
|
||||
while (*ip == '/')
|
||||
while (IS_DIR_SEP(*ip))
|
||||
/* skip any trailing slashes */
|
||||
++ip;
|
||||
/* no more components left? */
|
||||
@ -1526,7 +1526,7 @@ do_realpath(const char *upath)
|
||||
tp = shf_smprintf("%s%s%s", ldest, *ip ? "/" : "", ip);
|
||||
afree(ipath, ATEMP);
|
||||
ip = ipath = tp;
|
||||
if (ldest[0] != '/') {
|
||||
if (!IS_ABS_PATH(ldest)) {
|
||||
/* symlink target is a relative path */
|
||||
xp = Xrestpos(xs, xp, pos);
|
||||
} else
|
||||
@ -1539,7 +1539,7 @@ do_realpath(const char *upath)
|
||||
/* assert: xp == xs.beg => start of path */
|
||||
|
||||
/* exactly two leading slashes? (SUSv4 3.266) */
|
||||
if (ip[1] == '/' && ip[2] != '/') {
|
||||
if (IS_DIR_SEP(ip[1]) && !IS_DIR_SEP(ip[2])) {
|
||||
/* keep them, e.g. for UNC pathnames */
|
||||
Xput(xs, xp, '/');
|
||||
}
|
||||
@ -1564,7 +1564,7 @@ do_realpath(const char *upath)
|
||||
* if source path had a trailing slash, check if target path
|
||||
* is not a non-directory existing file
|
||||
*/
|
||||
if (ip > ipath && ip[-1] == '/') {
|
||||
if (ip > ipath && IS_DIR_SEP(ip[-1])) {
|
||||
if (stat(Xstring(xs, xp), &sb)) {
|
||||
if (errno != ENOENT)
|
||||
goto notfound;
|
||||
@ -1626,7 +1626,7 @@ make_path(const char *cwd, const char *file,
|
||||
if (!file)
|
||||
file = null;
|
||||
|
||||
if (file[0] == '/') {
|
||||
if (IS_ABS_PATH(file)) {
|
||||
*phys_pathp = 0;
|
||||
use_cdpath = false;
|
||||
} else {
|
||||
@ -1635,7 +1635,7 @@ make_path(const char *cwd, const char *file,
|
||||
|
||||
if (c == '.')
|
||||
c = file[2];
|
||||
if (c == '/' || c == '\0')
|
||||
if (IS_DIR_SEP(c) || c == '\0')
|
||||
use_cdpath = false;
|
||||
}
|
||||
|
||||
@ -1651,13 +1651,13 @@ make_path(const char *cwd, const char *file,
|
||||
*cdpathp = *pend ? pend + 1 : NULL;
|
||||
}
|
||||
|
||||
if ((!use_cdpath || !plen || plist[0] != '/') &&
|
||||
if ((!use_cdpath || !plen || !IS_ABS_PATH(plist)) &&
|
||||
(cwd && *cwd)) {
|
||||
len = strlen(cwd);
|
||||
XcheckN(*xsp, xp, len);
|
||||
memcpy(xp, cwd, len);
|
||||
xp += len;
|
||||
if (cwd[len - 1] != '/')
|
||||
if (!IS_DIR_SEP(cwd[len - 1]))
|
||||
Xput(*xsp, xp, '/');
|
||||
}
|
||||
*phys_pathp = Xlength(*xsp, xp);
|
||||
@ -1665,7 +1665,7 @@ make_path(const char *cwd, const char *file,
|
||||
XcheckN(*xsp, xp, plen);
|
||||
memcpy(xp, plist, plen);
|
||||
xp += plen;
|
||||
if (plist[plen - 1] != '/')
|
||||
if (!IS_DIR_SEP(plist[plen - 1]))
|
||||
Xput(*xsp, xp, '/');
|
||||
rval = 1;
|
||||
}
|
||||
@ -1706,8 +1706,11 @@ simplify_path(char *p)
|
||||
case 0:
|
||||
return;
|
||||
case '/':
|
||||
#ifdef __OS2__
|
||||
case '\\':
|
||||
#endif
|
||||
/* exactly two leading slashes? (SUSv4 3.266) */
|
||||
if (p[1] == '/' && p[2] != '/')
|
||||
if (IS_DIR_SEP(p[1]) && !IS_DIR_SEP(p[2]))
|
||||
/* keep them, e.g. for UNC pathnames */
|
||||
++p;
|
||||
needslash = true;
|
||||
@ -1719,14 +1722,14 @@ simplify_path(char *p)
|
||||
|
||||
while (*ip) {
|
||||
/* skip slashes in input */
|
||||
while (*ip == '/')
|
||||
while (IS_DIR_SEP(*ip))
|
||||
++ip;
|
||||
if (!*ip)
|
||||
break;
|
||||
|
||||
/* get next pathname component from input */
|
||||
tp = ip;
|
||||
while (*ip && *ip != '/')
|
||||
while (*ip && !IS_DIR_SEP(*ip))
|
||||
++ip;
|
||||
len = ip - tp;
|
||||
|
||||
@ -1737,7 +1740,7 @@ simplify_path(char *p)
|
||||
continue;
|
||||
else if (len == 2 && tp[1] == '.') {
|
||||
/* parent level, but how? */
|
||||
if (*p == '/')
|
||||
if (IS_ABS_PATH(p))
|
||||
/* absolute path, only one way */
|
||||
goto strip_last_component;
|
||||
else if (dp > sp) {
|
||||
@ -1746,7 +1749,7 @@ simplify_path(char *p)
|
||||
strip_last_component:
|
||||
/* strip off last pathname component */
|
||||
while (dp > sp)
|
||||
if (*--dp == '/')
|
||||
if (IS_DIR_SEP(*--dp))
|
||||
break;
|
||||
} else {
|
||||
/* relative path, at its beginning */
|
||||
@ -1937,7 +1940,7 @@ c_cd(const char **wp)
|
||||
/* Ignore failure (happens if readonly or integer) */
|
||||
setstr(oldpwd_s, current_wd, KSH_RETURN_ERROR);
|
||||
|
||||
if (Xstring(xs, xp)[0] != '/') {
|
||||
if (!IS_ABS_PATH(Xstring(xs, xp))) {
|
||||
pwd = NULL;
|
||||
} else if (!physical) {
|
||||
goto norealpath_PWD;
|
||||
|
26
sh.h
26
sh.h
@ -305,9 +305,35 @@ struct rusage {
|
||||
#ifdef __OS2__
|
||||
#define PATH_SEP ';'
|
||||
#define PATH_SEP_STR ";"
|
||||
#define IS_DIR_SEP(c) ({ \
|
||||
char _ch_ = (c); \
|
||||
(_ch_ == '/' || _ch_ == '\\'); \
|
||||
})
|
||||
#define IS_ABS_PATH(x) ({ \
|
||||
const char *_p_ = (x); \
|
||||
((ksh_isalphx(_p_[0]) && _p_[1] == ':') || IS_DIR_SEP(_p_[0])); \
|
||||
})
|
||||
#define ksh_strchr_dirsep(s) ({ \
|
||||
const char *_p_ = (s); \
|
||||
const char *_p1_ = strchr(_p_, '/'); \
|
||||
const char *_p2_ = strchr(_p_, '\\'); \
|
||||
const char *_p3_ = ((ksh_isalphx(_p_[0]) && _p_[1] == ':') \
|
||||
? (_p_ + 1) : NULL ); \
|
||||
_p1_ = _p1_ > _p2_ ? _p1_ : _p2_; \
|
||||
((char *)(_p1_ > _p3_ ? _p1_ : _p3_)); \
|
||||
})
|
||||
#define ksh_vstrchr_dirsep(s) ({ \
|
||||
const char *_p_ = (s); \
|
||||
(vstrchr((_p_), '/') || vstrchr((_p_), '\\') || \
|
||||
(ksh_isalphx(_p_[0]) && _p_[1] == ':')); \
|
||||
})
|
||||
#else
|
||||
#define PATH_SEP ':'
|
||||
#define PATH_SEP_STR ":"
|
||||
#define IS_DIR_SEP(c) ((c) == '/')
|
||||
#define IS_ABS_PATH(x) (IS_DIR_SEP((x)[0]))
|
||||
#define ksh_strchr_dirsep(s) (strchr((s), '/'))
|
||||
#define ksh_vstrchr_dirsep(s) (vstrchr((s), '/'))
|
||||
#endif
|
||||
|
||||
#ifdef MKSH__NO_PATH_MAX
|
||||
|
Loading…
x
Reference in New Issue
Block a user