• more comment and int→bool cleanup, add and improve some comments
• in interactive mode, always look up {LC_{ALL,CTYPE},LANG} environment variables if setlocale/nl_langinfo(CODESET) doesn’t suffice • add the ability to call any builtin (some don't make sense or wouldn't work) directly by analysing argv[0] • for direct builtin calls, the {LC_{ALL,CTYPE},LANG} environment variables determine utf8-mode, even if MKSH_ASSUME_UTF8 was set • when called as builtin, echo behaves POSIXish • add domainname as alias for true on MirBSD only, to be able to link it • sync mksh Makefiles with Build.sh output • adjust manpage wrt release plans • link some things to mksh now that we have callable builtins: bin/echo bin/kill bin/pwd bin/sleep (exact matches) bin/test bin/[ (were scripts before) bin/domainname=usr/bin/true usr/bin/false (move to /bin/ now) • drop linked utilities and, except for echo and kill, their manpages • adjust instbin and link a few more there as well
This commit is contained in:
parent
81b80af47a
commit
a796512040
27
Makefile
27
Makefile
@ -1,6 +1,6 @@
|
||||
# $MirOS: src/bin/mksh/Makefile,v 1.85 2011/01/30 02:28:31 tg Exp $
|
||||
# $MirOS: src/bin/mksh/Makefile,v 1.86 2011/02/11 01:18:14 tg Exp $
|
||||
#-
|
||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
# Thorsten Glaser <tg@mirbsd.org>
|
||||
#
|
||||
# Provided that these terms and disclaimer and all copyright notices
|
||||
@ -30,8 +30,10 @@ CPPFLAGS+= -DMKSH_ASSUME_UTF8 \
|
||||
-DHAVE_ATTRIBUTE_BOUNDED=1 -DHAVE_ATTRIBUTE_FORMAT=1 \
|
||||
-DHAVE_ATTRIBUTE_NONNULL=1 -DHAVE_ATTRIBUTE_NORETURN=1 \
|
||||
-DHAVE_ATTRIBUTE_UNUSED=1 -DHAVE_ATTRIBUTE_USED=1 \
|
||||
-DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_MKDEV_H=0 \
|
||||
-DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_SYSMACROS_H=0 -DHAVE_GRP_H=1 \
|
||||
-DHAVE_SYS_BSDTYPES_H=0 -DHAVE_SYS_FILE_H=1 \
|
||||
-DHAVE_SYS_MKDEV_H=0 -DHAVE_SYS_MMAN_H=1 \
|
||||
-DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_SELECT_H=1 \
|
||||
-DHAVE_SYS_SYSMACROS_H=0 -DHAVE_BSTRING_H=0 -DHAVE_GRP_H=1 \
|
||||
-DHAVE_LIBGEN_H=1 -DHAVE_LIBUTIL_H=0 -DHAVE_PATHS_H=1 \
|
||||
-DHAVE_STDBOOL_H=1 -DHAVE_STDINT_H=1 -DHAVE_STRINGS_H=1 \
|
||||
-DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 -DHAVE_CAN_INTTYPES=1 \
|
||||
@ -41,9 +43,10 @@ CPPFLAGS+= -DMKSH_ASSUME_UTF8 \
|
||||
-DHAVE_GETRUSAGE=1 -DHAVE_KILLPG=1 -DHAVE_MKNOD=0 \
|
||||
-DHAVE_MKSTEMP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=1 \
|
||||
-DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 \
|
||||
-DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRCASESTR=1 \
|
||||
-DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \
|
||||
-DHAVE_SYS_SIGLIST_DECL=1 -DHAVE_PERSISTENT_HISTORY=1
|
||||
-DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 \
|
||||
-DHAVE_STRCASESTR=1 -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 \
|
||||
-DHAVE_REVOKE_DECL=1 -DHAVE_SYS_SIGLIST_DECL=1 \
|
||||
-DHAVE_PERSISTENT_HISTORY=1
|
||||
COPTS+= -std=gnu99 -Wall
|
||||
.endif
|
||||
|
||||
@ -54,8 +57,14 @@ SRCS+= printf.c
|
||||
CPPFLAGS+= -DMKSH_PRINTF_BUILTIN
|
||||
.endif
|
||||
|
||||
LINKS+= ${BINDIR}/${PROG} ${BINDIR}/sh
|
||||
MLINKS+= ${PROG}.1 sh.1
|
||||
MANLINKS= [ false pwd sh sleep test true
|
||||
BINLINKS= ${MANLINKS} echo domainname kill
|
||||
.for _i in ${BINLINKS}
|
||||
LINKS+= ${BINDIR}/${PROG} ${BINDIR}/${_i}
|
||||
.endfor
|
||||
.for _i in ${MANLINKS}
|
||||
MLINKS+= ${PROG}.1 ${_i}.1
|
||||
.endfor
|
||||
|
||||
regress: ${PROG} check.pl check.t
|
||||
-rm -rf regress-dir
|
||||
|
4
check.t
4
check.t
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.406 2011/02/09 13:08:24 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.407 2011/02/11 01:18:15 tg Exp $
|
||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||
@ -25,7 +25,7 @@
|
||||
# http://www.research.att.com/~gsf/public/ifs.sh
|
||||
|
||||
expected-stdout:
|
||||
@(#)MIRBSD KSH R39 2011/02/09
|
||||
@(#)MIRBSD KSH R39 2011/02/11
|
||||
description:
|
||||
Check version of shell.
|
||||
stdin:
|
||||
|
162
exec.c
162
exec.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.85 2011/01/30 01:35:33 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.86 2011/02/11 01:18:16 tg Exp $");
|
||||
|
||||
#ifndef MKSH_DEFAULT_EXECSHELL
|
||||
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
|
||||
@ -44,7 +44,8 @@ static void dbteste_error(Test_env *, int, const char *);
|
||||
*/
|
||||
int
|
||||
execute(struct op * volatile t,
|
||||
volatile int flags, /* if XEXEC don't fork */
|
||||
/* if XEXEC don't fork */
|
||||
volatile int flags,
|
||||
volatile int * volatile xerrok)
|
||||
{
|
||||
int i;
|
||||
@ -72,7 +73,8 @@ execute(struct op * volatile t,
|
||||
if (trap)
|
||||
runtraps(0);
|
||||
|
||||
if (t->type == TCOM /* we want to run an executable... */) {
|
||||
/* we want to run an executable, do some variance checks */
|
||||
if (t->type == TCOM) {
|
||||
/* check if this is 'var=<<EOF' */
|
||||
if (
|
||||
/* we have zero arguments, i.e. no programme to run */
|
||||
@ -474,14 +476,16 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
volatile int rv = 0;
|
||||
const char *cp;
|
||||
const char **lastp;
|
||||
static struct op texec; /* Must be static (XXX but why?) */
|
||||
/* Must be static (XXX but why?) */
|
||||
static struct op texec;
|
||||
int type_flags;
|
||||
int keepasn_ok;
|
||||
int fcflags = FC_BI|FC_FUNC|FC_PATH;
|
||||
bool bourne_function_call = false;
|
||||
struct block *l_expand, *l_assign;
|
||||
|
||||
/* snag the last argument for $_ XXX not the same as AT&T ksh,
|
||||
/*
|
||||
* snag the last argument for $_ XXX not the same as AT&T ksh,
|
||||
* which only seems to set $_ after a newline (but not in
|
||||
* functions/dot scripts, but in interactive and script) -
|
||||
* perhaps save last arg here and set it in shell()?.
|
||||
@ -494,7 +498,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
KSH_RETURN_ERROR);
|
||||
}
|
||||
|
||||
/* Deal with the shell builtins builtin, exec and command since
|
||||
/**
|
||||
* Deal with the shell builtins builtin, exec and command since
|
||||
* they can be followed by other commands. This must be done before
|
||||
* we know if we should create a local block which must be done
|
||||
* before we can do a path search (in case the assignments change
|
||||
@ -527,14 +532,16 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
} else if (tp->val.f == c_command) {
|
||||
int optc, saw_p = 0;
|
||||
|
||||
/* Ugly dealing with options in two places (here and
|
||||
* in c_command(), but such is life)
|
||||
/*
|
||||
* Ugly dealing with options in two places (here
|
||||
* and in c_command(), but such is life)
|
||||
*/
|
||||
ksh_getopt_reset(&builtin_opt, 0);
|
||||
while ((optc = ksh_getopt(ap, &builtin_opt, ":p")) == 'p')
|
||||
saw_p = 1;
|
||||
if (optc != EOF)
|
||||
break; /* command -vV or something */
|
||||
/* command -vV or something */
|
||||
break;
|
||||
/* don't look for functions */
|
||||
fcflags = FC_BI|FC_PATH;
|
||||
if (saw_p) {
|
||||
@ -547,7 +554,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
fcflags |= FC_DEFPATH;
|
||||
}
|
||||
ap += builtin_opt.optind;
|
||||
/* POSIX says special builtins lose their status
|
||||
/*
|
||||
* POSIX says special builtins lose their status
|
||||
* if accessed using command.
|
||||
*/
|
||||
keepasn_ok = 0;
|
||||
@ -626,11 +634,14 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
}
|
||||
|
||||
switch (tp->type) {
|
||||
case CSHELL: /* shell built-in */
|
||||
|
||||
/* shell built-in */
|
||||
case CSHELL:
|
||||
rv = call_builtin(tp, (const char **)ap);
|
||||
break;
|
||||
|
||||
case CFUNC: { /* function call */
|
||||
/* function call */
|
||||
case CFUNC: {
|
||||
volatile unsigned char old_xflag;
|
||||
volatile Tflag old_inuse;
|
||||
const char * volatile old_kshname;
|
||||
@ -671,8 +682,9 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
tp = ftp;
|
||||
}
|
||||
|
||||
/* ksh functions set $0 to function name, POSIX functions leave
|
||||
* $0 unchanged.
|
||||
/*
|
||||
* ksh functions set $0 to function name, POSIX
|
||||
* functions leave $0 unchanged.
|
||||
*/
|
||||
old_kshname = kshname;
|
||||
if (tp->flag & FKSH)
|
||||
@ -683,7 +695,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
for (i = 0; *ap++ != NULL; i++)
|
||||
;
|
||||
e->loc->argc = i - 1;
|
||||
/* ksh-style functions handle getopts sanely,
|
||||
/*
|
||||
* ksh-style functions handle getopts sanely,
|
||||
* Bourne/POSIX functions are insane...
|
||||
*/
|
||||
if (tp->flag & FKSH) {
|
||||
@ -708,9 +721,10 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
kshname = old_kshname;
|
||||
Flag(FXTRACE) = old_xflag;
|
||||
tp->flag = (tp->flag & ~FINUSE) | old_inuse;
|
||||
/* Were we deleted while executing? If so, free the execution
|
||||
* tree. todo: Unfortunately, the table entry is never re-used
|
||||
* until the lookup table is expanded.
|
||||
/*
|
||||
* Were we deleted while executing? If so, free the
|
||||
* execution tree. TODO: Unfortunately, the table entry
|
||||
* is never re-used until the lookup table is expanded.
|
||||
*/
|
||||
if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) {
|
||||
if (tp->flag & ALLOC) {
|
||||
@ -738,10 +752,13 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
break;
|
||||
}
|
||||
|
||||
case CEXEC: /* executable command */
|
||||
case CTALIAS: /* tracked alias */
|
||||
/* executable command */
|
||||
case CEXEC:
|
||||
/* tracked alias */
|
||||
case CTALIAS:
|
||||
if (!(tp->flag&ISSET)) {
|
||||
/* errno_ will be set if the named command was found
|
||||
/*
|
||||
* errno_ will be set if the named command was found
|
||||
* but could not be executed (permissions, no execute
|
||||
* bit, directory, etc). Print out a (hopefully)
|
||||
* useful error message and set the exit status to 126.
|
||||
@ -749,7 +766,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
if (tp->u2.errno_) {
|
||||
warningf(true, "%s: %s: %s", cp,
|
||||
"can't execute", strerror(tp->u2.errno_));
|
||||
rv = 126; /* POSIX */
|
||||
/* POSIX */
|
||||
rv = 126;
|
||||
} else {
|
||||
warningf(true, "%s: %s", cp, "not found");
|
||||
rv = 127;
|
||||
@ -776,7 +794,8 @@ comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||
|
||||
/* to fork we set up a TEXEC node and call execute */
|
||||
texec.type = TEXEC;
|
||||
texec.left = t; /* for tprint */
|
||||
/* for tprint */
|
||||
texec.left = t;
|
||||
texec.str = tp->val.s;
|
||||
texec.args = ap;
|
||||
rv = exchild(&texec, flags, xerrok, -1);
|
||||
@ -796,7 +815,8 @@ scriptexec(struct op *tp, const char **ap)
|
||||
const char *sh;
|
||||
#ifndef MKSH_SMALL
|
||||
unsigned char *cp;
|
||||
char buf[64]; /* 64 == MAXINTERP in MirBSD <sys/param.h> */
|
||||
/* 64 == MAXINTERP in MirBSD <sys/param.h> */
|
||||
char buf[64];
|
||||
int fd;
|
||||
#endif
|
||||
union mksh_ccphack args, cap;
|
||||
@ -932,12 +952,14 @@ define(const char *name, struct op *t)
|
||||
|
||||
if (tp->flag & ISSET)
|
||||
was_set = true;
|
||||
/* If this function is currently being executed, we zap this
|
||||
* table entry so findfunc() won't see it
|
||||
/*
|
||||
* If this function is currently being executed, we zap
|
||||
* this table entry so findfunc() won't see it
|
||||
*/
|
||||
if (tp->flag & FINUSE) {
|
||||
tp->name[0] = '\0';
|
||||
tp->flag &= ~DEFINED; /* ensure it won't be found */
|
||||
/* ensure it won't be found */
|
||||
tp->flag &= ~DEFINED;
|
||||
tp->flag |= FDELETE;
|
||||
} else
|
||||
break;
|
||||
@ -948,7 +970,8 @@ define(const char *name, struct op *t)
|
||||
tfree(tp->val.t, tp->areap);
|
||||
}
|
||||
|
||||
if (t == NULL) { /* undefine */
|
||||
if (t == NULL) {
|
||||
/* undefine */
|
||||
ktdelete(tp);
|
||||
return (was_set ? 0 : 1);
|
||||
}
|
||||
@ -964,7 +987,7 @@ define(const char *name, struct op *t)
|
||||
/*
|
||||
* add builtin
|
||||
*/
|
||||
void
|
||||
const char *
|
||||
builtin(const char *name, int (*func) (const char **))
|
||||
{
|
||||
struct tbl *tp;
|
||||
@ -972,11 +995,14 @@ builtin(const char *name, int (*func) (const char **))
|
||||
|
||||
/* see if any flags should be set for this builtin */
|
||||
for (flag = 0; ; name++) {
|
||||
if (*name == '=') /* command does variable assignment */
|
||||
if (*name == '=')
|
||||
/* command does variable assignment */
|
||||
flag |= KEEPASN;
|
||||
else if (*name == '*') /* POSIX special builtin */
|
||||
else if (*name == '*')
|
||||
/* POSIX special builtin */
|
||||
flag |= SPEC_BI;
|
||||
else if (*name == '+') /* POSIX regular builtin */
|
||||
else if (*name == '+')
|
||||
/* POSIX regular builtin */
|
||||
flag |= REG_BI;
|
||||
else
|
||||
break;
|
||||
@ -986,6 +1012,8 @@ builtin(const char *name, int (*func) (const char **))
|
||||
tp->flag = DEFINED | flag;
|
||||
tp->type = CSHELL;
|
||||
tp->val.f = func;
|
||||
|
||||
return (name);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -998,8 +1026,10 @@ findcom(const char *name, int flags)
|
||||
static struct tbl temp;
|
||||
uint32_t h = hash(name);
|
||||
struct tbl *tp = NULL, *tbi;
|
||||
unsigned char insert = Flag(FTRACKALL); /* insert if not found */
|
||||
char *fpath; /* for function autoloading */
|
||||
/* insert if not found */
|
||||
unsigned char insert = Flag(FTRACKALL);
|
||||
/* for function autoloading */
|
||||
char *fpath;
|
||||
union mksh_cchack npath;
|
||||
|
||||
if (vstrchr(name, '/')) {
|
||||
@ -1009,7 +1039,8 @@ findcom(const char *name, int flags)
|
||||
goto Search;
|
||||
}
|
||||
tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h) : NULL;
|
||||
/* POSIX says special builtins first, then functions, then
|
||||
/*
|
||||
* POSIX says special builtins first, then functions, then
|
||||
* POSIX regular builtins, then search path...
|
||||
*/
|
||||
if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI))
|
||||
@ -1051,7 +1082,8 @@ findcom(const char *name, int flags)
|
||||
tp = &temp;
|
||||
tp->type = CEXEC;
|
||||
}
|
||||
tp->flag = DEFINED; /* make ~ISSET */
|
||||
/* make ~ISSET */
|
||||
tp->flag = DEFINED;
|
||||
}
|
||||
npath.ro = search(name, flags & FC_DEFPATH ? def_path : path,
|
||||
X_OK, &tp->u2.errno_);
|
||||
@ -1064,14 +1096,16 @@ findcom(const char *name, int flags)
|
||||
(fpath = str_val(global("FPATH"))) != null &&
|
||||
(npath.ro = search(name, fpath, R_OK,
|
||||
&tp->u2.errno_)) != NULL) {
|
||||
/* An undocumented feature of AT&T ksh is that it
|
||||
* searches FPATH if a command is not found, even
|
||||
* if the command hasn't been set up as an autoloaded
|
||||
* function (ie, no typeset -uf).
|
||||
/*
|
||||
* An undocumented feature of AT&T ksh is that
|
||||
* it searches FPATH if a command is not found,
|
||||
* even if the command hasn't been set up as an
|
||||
* autoloaded function (ie, no typeset -uf).
|
||||
*/
|
||||
tp = &temp;
|
||||
tp->type = CFUNC;
|
||||
tp->flag = DEFINED; /* make ~ISSET */
|
||||
/* make ~ISSET */
|
||||
tp->flag = DEFINED;
|
||||
tp->u.fpath = npath.ro;
|
||||
}
|
||||
}
|
||||
@ -1080,9 +1114,10 @@ findcom(const char *name, int flags)
|
||||
|
||||
/*
|
||||
* flush executable commands with relative paths
|
||||
* (just relative or all?)
|
||||
*/
|
||||
void
|
||||
flushcom(int all) /* just relative or all */
|
||||
flushcom(bool all)
|
||||
{
|
||||
struct tbl *tp;
|
||||
struct tstate ts;
|
||||
@ -1100,7 +1135,8 @@ flushcom(int all) /* just relative or all */
|
||||
/* Check if path is something we want to find. Returns -1 for failure. */
|
||||
int
|
||||
search_access(const char *lpath, int mode,
|
||||
int *errnop) /* set if candidate found, but not suitable */
|
||||
/* set if candidate found, but not suitable */
|
||||
int *errnop)
|
||||
{
|
||||
int ret, err = 0;
|
||||
struct stat statb;
|
||||
@ -1109,7 +1145,8 @@ search_access(const char *lpath, int mode,
|
||||
return (-1);
|
||||
ret = access(lpath, mode);
|
||||
if (ret < 0)
|
||||
err = errno; /* File exists, but we can't access it */
|
||||
/* File exists, but we can't access it */
|
||||
err = errno;
|
||||
else if (mode == X_OK && (!S_ISREG(statb.st_mode) ||
|
||||
!(statb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))) {
|
||||
/* This 'cause access() says root can execute everything */
|
||||
@ -1126,8 +1163,10 @@ search_access(const char *lpath, int mode,
|
||||
*/
|
||||
const char *
|
||||
search(const char *name, const char *lpath,
|
||||
int mode, /* R_OK or X_OK */
|
||||
int *errnop) /* set if candidate found, but not suitable */
|
||||
/* R_OK or X_OK */
|
||||
int mode,
|
||||
/* set if candidate found, but not suitable */
|
||||
int *errnop)
|
||||
{
|
||||
const char *sp, *p;
|
||||
char *xp;
|
||||
@ -1223,7 +1262,8 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
||||
|
||||
case IOWRITE:
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
/* The stat() is here to allow redirections to
|
||||
/*
|
||||
* The stat() is here to allow redirections to
|
||||
* things like /dev/null without error.
|
||||
*/
|
||||
if (Flag(FNOCLOBBER) && !(iop->flag & IOCLOB) &&
|
||||
@ -1247,7 +1287,8 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
||||
|
||||
do_open = 0;
|
||||
if (*cp == '-' && !cp[1]) {
|
||||
u = 1009; /* prevent error return below */
|
||||
/* prevent error return below */
|
||||
u = 1009;
|
||||
do_close = 1;
|
||||
} else if ((u = check_fd(cp,
|
||||
X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK),
|
||||
@ -1257,7 +1298,8 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
||||
return (-1);
|
||||
}
|
||||
if (u == iop->unit)
|
||||
return (0); /* "dup from" == "dup to" */
|
||||
/* "dup from" == "dup to" */
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1286,7 +1328,8 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
||||
if (u == iop->unit)
|
||||
e->savefd[iop->unit] = -1;
|
||||
else
|
||||
/* c_exec() assumes e->savefd[fd] set for any
|
||||
/*
|
||||
* c_exec() assumes e->savefd[fd] set for any
|
||||
* redirections. Ask savefd() not to close iop->unit;
|
||||
* this allows error messages to be seen if iop->unit
|
||||
* is 2; also means we can't lose the fd (eg, both
|
||||
@ -1312,17 +1355,21 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
||||
}
|
||||
if (iotype != IODUP)
|
||||
close(u);
|
||||
/* Touching any co-process fd in an empty exec
|
||||
/*
|
||||
* Touching any co-process fd in an empty exec
|
||||
* causes the shell to close its copies
|
||||
*/
|
||||
else if (tp && tp->type == CSHELL && tp->val.f == c_exec) {
|
||||
if (iop->flag & IORDUP) /* possible exec <&p */
|
||||
if (iop->flag & IORDUP)
|
||||
/* possible exec <&p */
|
||||
coproc_read_close(u);
|
||||
else /* possible exec >&p */
|
||||
else
|
||||
/* possible exec >&p */
|
||||
coproc_write_close(u);
|
||||
}
|
||||
}
|
||||
if (u == 2) /* Clear any write errors */
|
||||
if (u == 2)
|
||||
/* Clear any write errors */
|
||||
shf_reopen(2, SHF_WR, shl_out);
|
||||
return (0);
|
||||
}
|
||||
@ -1434,7 +1481,8 @@ do_selectargs(const char **ap, bool print_menu)
|
||||
for (argct = 0; ap[argct]; argct++)
|
||||
;
|
||||
while (1) {
|
||||
/* Menu is printed if
|
||||
/*-
|
||||
* Menu is printed if
|
||||
* - this is the first time around the select loop
|
||||
* - the user enters a blank line
|
||||
* - the REPLY parameter is empty
|
||||
@ -1573,8 +1621,10 @@ dbteste_isa(Test_env *te, Test_meta meta)
|
||||
|
||||
if (meta == TM_UNOP || meta == TM_BINOP) {
|
||||
if (uqword) {
|
||||
char buf[8]; /* longer than the longest operator */
|
||||
/* longer than the longest operator */
|
||||
char buf[8];
|
||||
char *q = buf;
|
||||
|
||||
for (p = *te->pos.wp;
|
||||
*p == CHAR && q < &buf[sizeof(buf) - 1]; p += 2)
|
||||
*q++ = p[1];
|
||||
|
16
funcs.c
16
funcs.c
@ -38,7 +38,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.169 2011/02/11 00:41:34 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.170 2011/02/11 01:18:17 tg Exp $");
|
||||
|
||||
#if HAVE_KILLPG
|
||||
/*
|
||||
@ -126,6 +126,10 @@ const struct builtin mkshbuiltins[] = {
|
||||
{"rename", c_rename},
|
||||
#if HAVE_SELECT
|
||||
{"sleep", c_sleep},
|
||||
#endif
|
||||
#ifdef __MirBSD__
|
||||
/* alias to "true" for historical reasons */
|
||||
{"domainname", c_label},
|
||||
#endif
|
||||
{NULL, (int (*)(const char **))NULL}
|
||||
};
|
||||
@ -497,7 +501,7 @@ c_cd(const char **wp)
|
||||
allocd = NULL;
|
||||
|
||||
/* Clear out tracked aliases with relative paths */
|
||||
flushcom(0);
|
||||
flushcom(false);
|
||||
|
||||
/*
|
||||
* Set OLDPWD (note: unsetting OLDPWD does not disable this
|
||||
@ -590,7 +594,7 @@ c_print(const char **wp)
|
||||
if (wp[0][0] == 'e') {
|
||||
/* echo builtin */
|
||||
wp++;
|
||||
if (Flag(FPOSIX) || Flag(FSH)) {
|
||||
if (Flag(FPOSIX) || Flag(FSH) || Flag(FAS_BUILTIN)) {
|
||||
/* Debian Policy 10.4 compliant "echo" builtin */
|
||||
if (*wp && !strcmp(*wp, "-n")) {
|
||||
/* we recognise "-n" only as the first arg */
|
||||
@ -1844,7 +1848,11 @@ c_bind(const char **wp)
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/* :, false and true (and ulimit if MKSH_NO_LIMITS) */
|
||||
/**
|
||||
* :, false and true
|
||||
* ulimit if MKSH_NO_LIMITS
|
||||
* domainname on MirBSD (hysterical raisins, just don't ask)
|
||||
*/
|
||||
int
|
||||
c_label(const char **wp)
|
||||
{
|
||||
|
274
main.c
274
main.c
@ -33,7 +33,7 @@
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.175 2011/01/21 21:07:11 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.176 2011/02/11 01:18:18 tg Exp $");
|
||||
|
||||
extern char **environ;
|
||||
|
||||
@ -67,7 +67,8 @@ static const char *initcoms[] = {
|
||||
T_alias,
|
||||
"integer=typeset -i",
|
||||
T_local_typeset,
|
||||
"hash=alias -t", /* not "alias -t --": hash -r needs to work */
|
||||
/* not "alias -t --": hash -r needs to work */
|
||||
"hash=alias -t",
|
||||
"type=whence -v",
|
||||
#if !defined(ANDROID) && !defined(MKSH_UNEMPLOYED)
|
||||
/* not in Android for political reasons */
|
||||
@ -111,12 +112,18 @@ rndsetup(void)
|
||||
char *cp;
|
||||
|
||||
cp = alloc(sizeof(*bufptr) - ALLOC_SIZE, APERM);
|
||||
bufptr = (void *)(cp - ALLOC_SIZE); /* undo what alloc() did */
|
||||
bufptr->dataptr = &rndsetupstate; /* PIE or something */
|
||||
bufptr->stkptr = &bufptr; /* ASLR in Win/Lin */
|
||||
bufptr->mallocptr = bufptr; /* randomised malloc in BSD */
|
||||
sigsetjmp(bufptr->jbuf, 1); /* glibc pointer guard */
|
||||
gettimeofday(&bufptr->tv, &bufptr->tz); /* introduce variation */
|
||||
/* undo what alloc() did to the malloc result address */
|
||||
bufptr = (void *)(cp - ALLOC_SIZE);
|
||||
/* PIE or something similar provides us with deltas here */
|
||||
bufptr->dataptr = &rndsetupstate;
|
||||
/* ASLR in at least Windows, Linux, some BSDs */
|
||||
bufptr->stkptr = &bufptr;
|
||||
/* randomised malloc in BSD (and possibly others) */
|
||||
bufptr->mallocptr = bufptr;
|
||||
/* glibc pointer guard */
|
||||
sigsetjmp(bufptr->jbuf, 1);
|
||||
/* introduce variation */
|
||||
gettimeofday(&bufptr->tv, &bufptr->tz);
|
||||
|
||||
oaat1_init_impl(h);
|
||||
/* variation through pid, ppid, and the works */
|
||||
@ -138,14 +145,18 @@ chvt_reinit(void)
|
||||
kshppid = getppid();
|
||||
}
|
||||
|
||||
static const char *empty_argv[] = {
|
||||
"mksh", NULL
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, const char *argv[])
|
||||
{
|
||||
int argi, i;
|
||||
Source *s;
|
||||
Source *s = NULL;
|
||||
struct block *l;
|
||||
unsigned char restricted, errexit, utf_flag;
|
||||
const char **wp;
|
||||
const char *ccp, **wp;
|
||||
struct tbl *vp;
|
||||
struct stat s_stdin;
|
||||
#if !defined(_PATH_DEFPATH) && defined(_CS_PATH)
|
||||
@ -158,16 +169,13 @@ main(int argc, const char *argv[])
|
||||
|
||||
/* make sure argv[] is sane */
|
||||
if (!*argv) {
|
||||
static const char *empty_argv[] = {
|
||||
"mksh", NULL
|
||||
};
|
||||
|
||||
argv = empty_argv;
|
||||
argc = 1;
|
||||
}
|
||||
kshname = *argv;
|
||||
kshname = argv[0];
|
||||
|
||||
ainit(&aperm); /* initialise permanent Area */
|
||||
/* initialise permanent Area */
|
||||
ainit(&aperm);
|
||||
|
||||
/* set up base environment */
|
||||
env.type = E_NONE;
|
||||
@ -178,9 +186,41 @@ main(int argc, const char *argv[])
|
||||
/* Do this first so output routines (eg, errorf, shellf) can work */
|
||||
initio();
|
||||
|
||||
argi = parse_args(argv, OF_FIRSTTIME, NULL);
|
||||
if (argi < 0)
|
||||
return (1);
|
||||
/* determine the basename (without '-' or path) of the executable */
|
||||
ccp = kshname;
|
||||
goto begin_parse_kshname;
|
||||
while ((i = ccp[argi++])) {
|
||||
if (i == '/') {
|
||||
ccp += argi;
|
||||
begin_parse_kshname:
|
||||
argi = 0;
|
||||
if (*ccp == '-')
|
||||
++ccp;
|
||||
}
|
||||
}
|
||||
if (!*ccp)
|
||||
ccp = empty_argv[0];
|
||||
|
||||
/* define built-in commands and see if we were called as one */
|
||||
ktinit(&builtins, APERM,
|
||||
/* must be 80% of 2^n (currently 44 builtins) */ 64);
|
||||
for (i = 0; mkshbuiltins[i].name != NULL; i++)
|
||||
if (!strcmp(ccp, builtin(mkshbuiltins[i].name,
|
||||
mkshbuiltins[i].func)))
|
||||
Flag(FAS_BUILTIN) = 1;
|
||||
|
||||
if (!Flag(FAS_BUILTIN)) {
|
||||
/* check for -T option early */
|
||||
argi = parse_args(argv, OF_FIRSTTIME, NULL);
|
||||
if (argi < 0)
|
||||
return (1);
|
||||
|
||||
#ifdef MKSH_BINSHREDUCED
|
||||
/* set FSH if we're called as -sh or /bin/sh or so */
|
||||
if (!strcmp(ccp, "sh"))
|
||||
change_flag(FSH, OF_FIRSTTIME, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
initvar();
|
||||
|
||||
@ -200,12 +240,6 @@ main(int argc, const char *argv[])
|
||||
/* define shell keywords */
|
||||
initkeywords();
|
||||
|
||||
/* define built-in commands */
|
||||
ktinit(&builtins, APERM,
|
||||
/* must be 80% of 2^n (currently 44 builtins) */ 64);
|
||||
for (i = 0; mkshbuiltins[i].name != NULL; i++)
|
||||
builtin(mkshbuiltins[i].name, mkshbuiltins[i].func);
|
||||
|
||||
init_histvec();
|
||||
|
||||
#ifdef _PATH_DEFPATH
|
||||
@ -260,28 +294,13 @@ main(int argc, const char *argv[])
|
||||
Flag(FVITABCOMPLETE) = 1;
|
||||
#endif
|
||||
|
||||
#ifdef MKSH_BINSHREDUCED
|
||||
/* set FSH if we're called as -sh or /bin/sh or so */
|
||||
{
|
||||
const char *cc;
|
||||
|
||||
cc = kshname;
|
||||
i = 0; argi = 0;
|
||||
while (cc[i] != '\0')
|
||||
/* the following line matches '-' and '/' ;-) */
|
||||
if ((cc[i++] | 2) == '/')
|
||||
argi = i;
|
||||
if (((cc[argi] | 0x20) == 's') && ((cc[argi + 1] | 0x20) == 'h'))
|
||||
change_flag(FSH, OF_FIRSTTIME, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* import environment */
|
||||
if (environ != NULL)
|
||||
for (wp = (const char **)environ; *wp != NULL; wp++)
|
||||
typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
|
||||
|
||||
typeset(initifs, 0, 0, 0, 0); /* for security */
|
||||
/* for security */
|
||||
typeset(initifs, 0, 0, 0, 0);
|
||||
|
||||
/* assign default shell variable values */
|
||||
substitute(initsubs, 0);
|
||||
@ -356,15 +375,20 @@ main(int argc, const char *argv[])
|
||||
/* this to note if utf-8 mode is set on command line (see below) */
|
||||
UTFMODE = 2;
|
||||
|
||||
argi = parse_args(argv, OF_CMDLINE, NULL);
|
||||
if (argi < 0)
|
||||
return (1);
|
||||
if (!Flag(FAS_BUILTIN)) {
|
||||
argi = parse_args(argv, OF_CMDLINE, NULL);
|
||||
if (argi < 0)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* process this later only, default to off (hysterical raisins) */
|
||||
utf_flag = UTFMODE;
|
||||
UTFMODE = 0;
|
||||
|
||||
if (Flag(FCOMMAND)) {
|
||||
if (Flag(FAS_BUILTIN)) {
|
||||
/* auto-detect from environment variables, always */
|
||||
utf_flag = 3;
|
||||
} else if (Flag(FCOMMAND)) {
|
||||
s = pushs(SSTRING, ATEMP);
|
||||
if (!(s->start = s->str = argv[argi++]))
|
||||
errorf("%s %s", "-c", "requires an argument");
|
||||
@ -410,37 +434,17 @@ main(int argc, const char *argv[])
|
||||
|
||||
/* initialise job control */
|
||||
j_init();
|
||||
/* set: 0/1; unset: 2->0 */
|
||||
UTFMODE = utf_flag & 1;
|
||||
/* Do this after j_init(), as tty_fd is not initialised until then */
|
||||
if (Flag(FTALKING)) {
|
||||
if (utf_flag == 2) {
|
||||
#ifndef MKSH_ASSUME_UTF8
|
||||
#define isuc(x) (((x) != NULL) && \
|
||||
(stristr((x), "UTF-8") || stristr((x), "utf8")))
|
||||
/* Check if we're in a UTF-8 locale */
|
||||
const char *ccp;
|
||||
|
||||
#if HAVE_SETLOCALE_CTYPE
|
||||
ccp = setlocale(LC_CTYPE, "");
|
||||
#if HAVE_LANGINFO_CODESET
|
||||
if (!isuc(ccp))
|
||||
ccp = nl_langinfo(CODESET);
|
||||
#endif
|
||||
#else
|
||||
/* these were imported from environ earlier */
|
||||
ccp = str_val(global("LC_ALL"));
|
||||
if (ccp == null)
|
||||
ccp = str_val(global("LC_CTYPE"));
|
||||
if (ccp == null)
|
||||
ccp = str_val(global("LANG"));
|
||||
#endif
|
||||
UTFMODE = isuc(ccp);
|
||||
#undef isuc
|
||||
/* auto-detect from locale or environment */
|
||||
utf_flag = 4;
|
||||
#elif MKSH_ASSUME_UTF8
|
||||
UTFMODE = 1;
|
||||
utf_flag = 1;
|
||||
#else
|
||||
UTFMODE = 0;
|
||||
/* always disable UTF-8 (for interactive) */
|
||||
utf_flag = 0;
|
||||
#endif
|
||||
}
|
||||
x_init();
|
||||
@ -453,10 +457,62 @@ main(int argc, const char *argv[])
|
||||
#endif
|
||||
|
||||
l = e->loc;
|
||||
l->argv = &argv[argi - 1];
|
||||
l->argc = argc - argi;
|
||||
l->argv[0] = kshname;
|
||||
getopts_reset(1);
|
||||
if (Flag(FAS_BUILTIN)) {
|
||||
l->argc = argc;
|
||||
l->argv = argv;
|
||||
l->argv[0] = ccp;
|
||||
} else {
|
||||
l->argc = argc - argi;
|
||||
l->argv = &argv[argi - 1];
|
||||
l->argv[0] = kshname;
|
||||
getopts_reset(1);
|
||||
}
|
||||
|
||||
/* divine the initial state of the utf8-mode Flag */
|
||||
#define isuc(x) (((x) != NULL) && \
|
||||
(stristr((x), "UTF-8") || stristr((x), "utf8")))
|
||||
ccp = null;
|
||||
switch (utf_flag) {
|
||||
|
||||
/* auto-detect from locale or environment */
|
||||
case 4:
|
||||
#if HAVE_SETLOCALE_CTYPE
|
||||
ccp = setlocale(LC_CTYPE, "");
|
||||
#if HAVE_LANGINFO_CODESET
|
||||
if (!isuc(ccp))
|
||||
ccp = nl_langinfo(CODESET);
|
||||
#endif
|
||||
if (!isuc(ccp))
|
||||
ccp = null;
|
||||
/* FALLTHROUGH */
|
||||
#endif
|
||||
|
||||
/* auto-detect from environment */
|
||||
case 3:
|
||||
/* these were imported from environ earlier */
|
||||
if (ccp == null)
|
||||
ccp = str_val(global("LC_ALL"));
|
||||
if (ccp == null)
|
||||
ccp = str_val(global("LC_CTYPE"));
|
||||
if (ccp == null)
|
||||
ccp = str_val(global("LANG"));
|
||||
UTFMODE = isuc(ccp);
|
||||
break;
|
||||
|
||||
/* not set on command line, not FTALKING */
|
||||
case 2:
|
||||
/* unknown values */
|
||||
default:
|
||||
utf_flag = 0;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
/* known values */
|
||||
case 1:
|
||||
case 0:
|
||||
UTFMODE = utf_flag;
|
||||
break;
|
||||
}
|
||||
#undef isuc
|
||||
|
||||
/* Disable during .profile/ENV reading */
|
||||
restricted = Flag(FRESTRICTED);
|
||||
@ -505,7 +561,11 @@ main(int argc, const char *argv[])
|
||||
hist_init(s);
|
||||
alarm_init();
|
||||
} else
|
||||
Flag(FTRACKALL) = 1; /* set after ENV */
|
||||
/* set after ENV */
|
||||
Flag(FTRACKALL) = 1;
|
||||
|
||||
if (Flag(FAS_BUILTIN))
|
||||
return (shcomexec(l->argv));
|
||||
|
||||
/* doesn't return */
|
||||
shell(s, true);
|
||||
@ -543,7 +603,8 @@ include(const char *name, int argc, const char **argv, int intr_ok)
|
||||
switch (i) {
|
||||
case LRETURN:
|
||||
case LERROR:
|
||||
return (exstat & 0xff); /* see below */
|
||||
/* see below */
|
||||
return (exstat & 0xFF);
|
||||
case LINTR:
|
||||
/*
|
||||
* intr_ok is set if we are including .profile or $ENV.
|
||||
@ -575,7 +636,8 @@ include(const char *name, int argc, const char **argv, int intr_ok)
|
||||
e->loc->argv = old_argv;
|
||||
e->loc->argc = old_argc;
|
||||
}
|
||||
return (i & 0xff); /* & 0xff to ensure value not -1 */
|
||||
/* & 0xff to ensure value not -1 */
|
||||
return (i & 0xFF);
|
||||
}
|
||||
|
||||
/* spawn a command into a shell optionally keeping track of the line number */
|
||||
@ -603,7 +665,8 @@ shell(Source * volatile s, volatile int toplevel)
|
||||
Source *volatile old_source = source;
|
||||
int i;
|
||||
|
||||
s->flags |= SF_FIRST; /* enable UTF-8 BOM check */
|
||||
/* enable UTF-8 BOM check */
|
||||
s->flags |= SF_FIRST;
|
||||
|
||||
newenv(E_PARSE);
|
||||
if (interactive)
|
||||
@ -611,7 +674,8 @@ shell(Source * volatile s, volatile int toplevel)
|
||||
i = sigsetjmp(e->jbuf, 0);
|
||||
if (i) {
|
||||
switch (i) {
|
||||
case LINTR: /* we get here if SIGINT not caught or ignored */
|
||||
case LINTR:
|
||||
/* we get here if SIGINT not caught or ignored */
|
||||
case LERROR:
|
||||
case LSHELL:
|
||||
if (interactive) {
|
||||
@ -641,7 +705,8 @@ shell(Source * volatile s, volatile int toplevel)
|
||||
case LRETURN:
|
||||
source = old_source;
|
||||
quitenv(NULL);
|
||||
unwind(i); /* keep on going */
|
||||
/* keep on going */
|
||||
unwind(i);
|
||||
/* NOTREACHED */
|
||||
default:
|
||||
source = old_source;
|
||||
@ -745,7 +810,8 @@ newenv(int type)
|
||||
* so first get the actually used memory, then assign it
|
||||
*/
|
||||
cp = alloc(sizeof(struct env) - ALLOC_SIZE, ATEMP);
|
||||
ep = (void *)(cp - ALLOC_SIZE); /* undo what alloc() did */
|
||||
/* undo what alloc() did to the malloc result address */
|
||||
ep = (void *)(cp - ALLOC_SIZE);
|
||||
/* initialise public members of struct env (not the ALLOC_ITEM) */
|
||||
ainit(&ep->area);
|
||||
ep->oenv = e;
|
||||
@ -772,7 +838,8 @@ quitenv(struct shf *shf)
|
||||
/* if ep->savefd[fd] < 0, means fd was closed */
|
||||
if (ep->savefd[fd])
|
||||
restfd(fd, ep->savefd[fd]);
|
||||
if (ep->savefd[2]) /* Clear any write errors */
|
||||
if (ep->savefd[2])
|
||||
/* Clear any write errors */
|
||||
shf_reopen(2, SHF_WR, shl_out);
|
||||
}
|
||||
/*
|
||||
@ -780,7 +847,8 @@ quitenv(struct shf *shf)
|
||||
* Either main shell is exiting or cleanup_parents_env() was called.
|
||||
*/
|
||||
if (ep->oenv == NULL) {
|
||||
if (ep->type == E_NONE) { /* Main shell exiting? */
|
||||
if (ep->type == E_NONE) {
|
||||
/* Main shell exiting? */
|
||||
#if HAVE_PERSISTENT_HISTORY
|
||||
if (Flag(FTALKING))
|
||||
hist_finish();
|
||||
@ -946,7 +1014,9 @@ errorf(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
shl_stdout_ok = false; /* debugging: note that stdout not valid */
|
||||
/* debugging: note that stdout not valid */
|
||||
shl_stdout_ok = false;
|
||||
|
||||
exstat = 1;
|
||||
if (*fmt != 1) {
|
||||
error_prefix(true);
|
||||
@ -982,12 +1052,14 @@ bi_errorf(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
shl_stdout_ok = false; /* debugging: note that stdout not valid */
|
||||
/* debugging: note that stdout not valid */
|
||||
shl_stdout_ok = false;
|
||||
|
||||
exstat = 1;
|
||||
if (*fmt != 1) {
|
||||
error_prefix(true);
|
||||
/* not set when main() calls parse_args() */
|
||||
if (builtin_argv0)
|
||||
if (builtin_argv0 && builtin_argv0 != kshname)
|
||||
shf_fprintf(shl_out, "%s: ", builtin_argv0);
|
||||
va_start(va, fmt);
|
||||
shf_vfprintf(shl_out, fmt, va);
|
||||
@ -1058,7 +1130,8 @@ shellf(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
if (!initio_done) /* shl_out may not be set up yet... */
|
||||
if (!initio_done)
|
||||
/* shl_out may not be set up yet... */
|
||||
return;
|
||||
va_start(va, fmt);
|
||||
shf_vfprintf(shl_out, fmt, va);
|
||||
@ -1094,9 +1167,11 @@ struct shf shf_iob[3];
|
||||
void
|
||||
initio(void)
|
||||
{
|
||||
shf_fdopen(1, SHF_WR, shl_stdout); /* force buffer allocation */
|
||||
/* force buffer allocation */
|
||||
shf_fdopen(1, SHF_WR, shl_stdout);
|
||||
shf_fdopen(2, SHF_WR, shl_out);
|
||||
shf_fdopen(2, SHF_WR, shl_spare); /* force buffer allocation */
|
||||
/* force buffer allocation */
|
||||
shf_fdopen(2, SHF_WR, shl_spare);
|
||||
initio_done = 1;
|
||||
}
|
||||
|
||||
@ -1110,7 +1185,7 @@ ksh_dup2(int ofd, int nfd, bool errok)
|
||||
errorf("too many files open in shell");
|
||||
|
||||
#ifdef __ultrix
|
||||
/* XXX imake style */
|
||||
/*XXX imake style */
|
||||
if (rv >= 0)
|
||||
fcntl(nfd, F_SETFD, 0);
|
||||
#endif
|
||||
@ -1119,8 +1194,8 @@ ksh_dup2(int ofd, int nfd, bool errok)
|
||||
}
|
||||
|
||||
/*
|
||||
* move fd from user space (0<=fd<10) to shell space (fd>=10),
|
||||
* set close-on-exec flag.
|
||||
* Move fd from user space (0 <= fd < 10) to shell space (fd >= 10),
|
||||
* set close-on-exec flag. See FDBASE in sh.h, maybe 24 not 10 here.
|
||||
*/
|
||||
short
|
||||
savefd(int fd)
|
||||
@ -1141,10 +1216,12 @@ restfd(int fd, int ofd)
|
||||
{
|
||||
if (fd == 2)
|
||||
shf_flush(&shf_iob[fd]);
|
||||
if (ofd < 0) /* original fd closed */
|
||||
if (ofd < 0)
|
||||
/* original fd closed */
|
||||
close(fd);
|
||||
else if (fd != ofd) {
|
||||
ksh_dup2(ofd, fd, true); /* XXX: what to do if this fails? */
|
||||
/*XXX: what to do if this dup fails? */
|
||||
ksh_dup2(ofd, fd, true);
|
||||
close(ofd);
|
||||
}
|
||||
}
|
||||
@ -1366,11 +1443,14 @@ texpand(struct table *tp, size_t nsize)
|
||||
for (i = 0; i < nsize; i++)
|
||||
ntblp[i] = NULL;
|
||||
tp->size = nsize;
|
||||
tp->nfree = (nsize * 4) / 5; /* table can get 80% full */
|
||||
/* table can get 80% full */
|
||||
tp->nfree = (nsize * 4) / 5;
|
||||
tp->tbls = ntblp;
|
||||
if (otblp == NULL)
|
||||
return;
|
||||
nsize--; /* from here on nsize := mask */
|
||||
|
||||
/* from here on nsize := mask */
|
||||
nsize--;
|
||||
for (i = 0; i < osize; i++)
|
||||
if ((tblp = otblp[i]) != NULL) {
|
||||
if ((tblp->flag & DEFINED)) {
|
||||
|
129
misc.c
129
misc.c
@ -29,9 +29,10 @@
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.150 2011/01/21 21:04:45 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.151 2011/02/11 01:18:19 tg Exp $");
|
||||
|
||||
unsigned char chtypes[UCHAR_MAX + 1]; /* type bits for unsigned char */
|
||||
/* type bits for unsigned char */
|
||||
unsigned char chtypes[UCHAR_MAX + 1];
|
||||
|
||||
static int do_gmatch(const unsigned char *, const unsigned char *,
|
||||
const unsigned char *, const unsigned char *);
|
||||
@ -62,7 +63,8 @@ setctypes(const char *s, int t)
|
||||
if (t & C_IFS) {
|
||||
for (i = 0; i < UCHAR_MAX + 1; i++)
|
||||
chtypes[i] &= ~C_IFS;
|
||||
chtypes[0] |= C_IFS; /* include \0 in C_IFS */
|
||||
/* include \0 in C_IFS */
|
||||
chtypes[0] |= C_IFS;
|
||||
}
|
||||
while (*s != 0)
|
||||
chtypes[(unsigned char)*s++] |= t;
|
||||
@ -79,7 +81,8 @@ initctypes(void)
|
||||
chtypes[c] |= C_ALPHA;
|
||||
chtypes['_'] |= C_ALPHA;
|
||||
setctypes("0123456789", C_DIGIT);
|
||||
setctypes(" \t\n|&;<>()", C_LEX1); /* \0 added automatically */
|
||||
/* \0 added automatically */
|
||||
setctypes(" \t\n|&;<>()", C_LEX1);
|
||||
setctypes("*@#!$-?", C_VAR1);
|
||||
setctypes(" \t\n", C_IFSWS);
|
||||
setctypes("=-+?", C_SUBOP1);
|
||||
@ -209,7 +212,8 @@ change_flag(enum sh_flag f, int what, unsigned int newval)
|
||||
unsigned char oldval;
|
||||
|
||||
oldval = Flag(f);
|
||||
Flag(f) = newval ? 1 : 0; /* needed for tristates */
|
||||
/* needed for tristates */
|
||||
Flag(f) = newval ? 1 : 0;
|
||||
#ifndef MKSH_UNEMPLOYED
|
||||
if (f == FMONITOR) {
|
||||
if (what != OF_CMDLINE && newval != oldval)
|
||||
@ -256,12 +260,14 @@ change_flag(enum sh_flag f, int what, unsigned int newval)
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse command line & set command arguments. Returns the index of
|
||||
/*
|
||||
* Parse command line and set command arguments. Returns the index of
|
||||
* non-option arguments, -1 if there is an error.
|
||||
*/
|
||||
int
|
||||
parse_args(const char **argv,
|
||||
int what, /* OF_CMDLINE or OF_SET */
|
||||
/* OF_CMDLINE or OF_SET */
|
||||
int what,
|
||||
bool *setargsp)
|
||||
{
|
||||
static char cmd_opts[NELEM(options) + 5]; /* o:T:\0 */
|
||||
@ -304,7 +310,8 @@ parse_args(const char **argv,
|
||||
|
||||
if (what == OF_CMDLINE) {
|
||||
const char *p = argv[0], *q;
|
||||
/* Set FLOGIN before parsing options so user can clear
|
||||
/*
|
||||
* Set FLOGIN before parsing options so user can clear
|
||||
* flag using +l.
|
||||
*/
|
||||
if (*p != '-')
|
||||
@ -332,7 +339,8 @@ parse_args(const char **argv,
|
||||
if (what == OF_FIRSTTIME)
|
||||
break;
|
||||
if (go.optarg == NULL) {
|
||||
/* lone -o: print options
|
||||
/*
|
||||
* lone -o: print options
|
||||
*
|
||||
* Note that on the command line, -o requires
|
||||
* an option (ie, can't get here if what is
|
||||
@ -351,7 +359,8 @@ parse_args(const char **argv,
|
||||
}
|
||||
#endif
|
||||
if ((i != (size_t)-1) && set == Flag(i))
|
||||
/* Don't check the context if the flag
|
||||
/*
|
||||
* Don't check the context if the flag
|
||||
* isn't changing - makes "set -o interactive"
|
||||
* work if you're already interactive. Needed
|
||||
* if the output of "set +o" is to be used.
|
||||
@ -495,7 +504,8 @@ gmatchx(const char *s, const char *p, bool isfile)
|
||||
|
||||
se = s + strlen(s);
|
||||
pe = p + strlen(p);
|
||||
/* isfile is false iff no syntax check has been done on
|
||||
/*
|
||||
* isfile is false iff no syntax check has been done on
|
||||
* the pattern. If check fails, just to a strcmp().
|
||||
*/
|
||||
if (!isfile && !has_globbing(p, pe)) {
|
||||
@ -509,7 +519,8 @@ gmatchx(const char *s, const char *p, bool isfile)
|
||||
(const unsigned char *) p, (const unsigned char *) pe));
|
||||
}
|
||||
|
||||
/* Returns if p is a syntacticly correct globbing pattern, false
|
||||
/**
|
||||
* Returns if p is a syntacticly correct globbing pattern, false
|
||||
* if it contains no pattern characters or if there is a syntax error.
|
||||
* Syntax errors are:
|
||||
* - [ with no closing ]
|
||||
@ -517,14 +528,14 @@ gmatchx(const char *s, const char *p, bool isfile)
|
||||
* - [...] and *(...) not nested (eg, [a$(b|]c), *(a[b|c]d))
|
||||
*/
|
||||
/*XXX
|
||||
- if no magic,
|
||||
if dest given, copy to dst
|
||||
return ?
|
||||
- if magic && (no globbing || syntax error)
|
||||
debunk to dst
|
||||
return ?
|
||||
- return ?
|
||||
*/
|
||||
* - if no magic,
|
||||
* if dest given, copy to dst
|
||||
* return ?
|
||||
* - if magic && (no globbing || syntax error)
|
||||
* debunk to dst
|
||||
* return ?
|
||||
* - return ?
|
||||
*/
|
||||
int
|
||||
has_globbing(const char *xp, const char *xpe)
|
||||
{
|
||||
@ -532,42 +543,46 @@ has_globbing(const char *xp, const char *xpe)
|
||||
const unsigned char *pe = (const unsigned char *) xpe;
|
||||
int c;
|
||||
int nest = 0, bnest = 0;
|
||||
int saw_glob = 0;
|
||||
int in_bracket = 0; /* inside [...] */
|
||||
bool saw_glob = false;
|
||||
/* inside [...] */
|
||||
bool in_bracket = false;
|
||||
|
||||
for (; p < pe; p++) {
|
||||
if (!ISMAGIC(*p))
|
||||
continue;
|
||||
if ((c = *++p) == '*' || c == '?')
|
||||
saw_glob = 1;
|
||||
saw_glob = true;
|
||||
else if (c == '[') {
|
||||
if (!in_bracket) {
|
||||
saw_glob = 1;
|
||||
in_bracket = 1;
|
||||
saw_glob = true;
|
||||
in_bracket = true;
|
||||
if (ISMAGIC(p[1]) && p[2] == NOT)
|
||||
p += 2;
|
||||
if (ISMAGIC(p[1]) && p[2] == ']')
|
||||
p += 2;
|
||||
}
|
||||
/* XXX Do we need to check ranges here? POSIX Q */
|
||||
/*XXX Do we need to check ranges here? POSIX Q */
|
||||
} else if (c == ']') {
|
||||
if (in_bracket) {
|
||||
if (bnest) /* [a*(b]) */
|
||||
if (bnest)
|
||||
/* [a*(b]) */
|
||||
return (0);
|
||||
in_bracket = 0;
|
||||
in_bracket = false;
|
||||
}
|
||||
} else if ((c & 0x80) && vstrchr("*+?@! ", c & 0x7f)) {
|
||||
saw_glob = 1;
|
||||
saw_glob = true;
|
||||
if (in_bracket)
|
||||
bnest++;
|
||||
else
|
||||
nest++;
|
||||
} else if (c == '|') {
|
||||
if (in_bracket && !bnest) /* *(a[foo|bar]) */
|
||||
if (in_bracket && !bnest)
|
||||
/* *(a[foo|bar]) */
|
||||
return (0);
|
||||
} else if (c == /*(*/ ')') {
|
||||
if (in_bracket) {
|
||||
if (!bnest--) /* *(a[b)c] */
|
||||
if (!bnest--)
|
||||
/* *(a[b)c] */
|
||||
return (0);
|
||||
} else if (nest)
|
||||
nest--;
|
||||
@ -629,8 +644,11 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
|
||||
* [*+?@!](pattern|pattern|..)
|
||||
* This is also needed for ${..%..}, etc.
|
||||
*/
|
||||
case 0x80|'+': /* matches one or more times */
|
||||
case 0x80|'*': /* matches zero or more times */
|
||||
|
||||
/* matches one or more times */
|
||||
case 0x80|'+':
|
||||
/* matches zero or more times */
|
||||
case 0x80|'*':
|
||||
if (!(prest = pat_scan(p, pe, 0)))
|
||||
return (0);
|
||||
s--;
|
||||
@ -652,9 +670,12 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
|
||||
}
|
||||
return (0);
|
||||
|
||||
case 0x80|'?': /* matches zero or once */
|
||||
case 0x80|'@': /* matches one of the patterns */
|
||||
case 0x80|' ': /* simile for @ */
|
||||
/* matches zero or once */
|
||||
case 0x80|'?':
|
||||
/* matches one of the patterns */
|
||||
case 0x80|'@':
|
||||
/* simile for @ */
|
||||
case 0x80|' ':
|
||||
if (!(prest = pat_scan(p, pe, 0)))
|
||||
return (0);
|
||||
s--;
|
||||
@ -675,7 +696,8 @@ do_gmatch(const unsigned char *s, const unsigned char *se,
|
||||
}
|
||||
return (0);
|
||||
|
||||
case 0x80|'!': /* matches none of the patterns */
|
||||
/* matches none of the patterns */
|
||||
case 0x80|'!':
|
||||
if (!(prest = pat_scan(p, pe, 0)))
|
||||
return (0);
|
||||
s--;
|
||||
@ -733,7 +755,8 @@ cclass(const unsigned char *p, int sub)
|
||||
return (sub == '[' ? orig_p : NULL);
|
||||
if (ISMAGIC(p[0]) && p[1] == '-' &&
|
||||
(!ISMAGIC(p[2]) || p[3] != ']')) {
|
||||
p += 2; /* MAGIC- */
|
||||
/* MAGIC- */
|
||||
p += 2;
|
||||
d = *p++;
|
||||
if (ISMAGIC(d)) {
|
||||
d = *p++;
|
||||
@ -789,7 +812,8 @@ ksh_getopt_reset(Getopt *go, int flags)
|
||||
}
|
||||
|
||||
|
||||
/* getopt() used for shell built-in commands, the getopts command, and
|
||||
/**
|
||||
* getopt() used for shell built-in commands, the getopts command, and
|
||||
* command line options.
|
||||
* A leading ':' in options means don't print errors, instead return '?'
|
||||
* or ':' and set go->optarg to the offending option character.
|
||||
@ -830,7 +854,8 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
|
||||
return (-1);
|
||||
}
|
||||
if (arg == NULL ||
|
||||
((flag != '-' ) && /* neither a - nor a + (if + allowed) */
|
||||
((flag != '-' ) &&
|
||||
/* neither a - nor a + (if + allowed) */
|
||||
(!(go->flags & GF_PLUSOPT) || flag != '+')) ||
|
||||
(c = arg[1]) == '\0') {
|
||||
go->p = 0;
|
||||
@ -856,7 +881,8 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
|
||||
}
|
||||
return ('?');
|
||||
}
|
||||
/* : means argument must be present, may be part of option argument
|
||||
/**
|
||||
* : means argument must be present, may be part of option argument
|
||||
* or the next argument
|
||||
* ; same as : but argument may be missing
|
||||
* , means argument is part of option argument, and may be null.
|
||||
@ -888,7 +914,8 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
|
||||
go->optarg = argv[go->optind - 1] + go->p;
|
||||
go->p = 0;
|
||||
} else if (*o == '#') {
|
||||
/* argument is optional and may be attached or unattached
|
||||
/*
|
||||
* argument is optional and may be attached or unattached
|
||||
* but must start with a digit. optarg is set to 0 if the
|
||||
* argument is missing.
|
||||
*/
|
||||
@ -909,7 +936,8 @@ ksh_getopt(const char **argv, Getopt *go, const char *optionsp)
|
||||
return (c);
|
||||
}
|
||||
|
||||
/* print variable/alias value using necessary quotes
|
||||
/*
|
||||
* print variable/alias value using necessary quotes
|
||||
* (POSIX says they should be suitable for re-entry...)
|
||||
* No trailing newline is printed.
|
||||
*/
|
||||
@ -1025,8 +1053,9 @@ strip_nuls(char *buf, int nbytes)
|
||||
{
|
||||
char *dst;
|
||||
|
||||
/* nbytes check because some systems (older FreeBSDs) have a buggy
|
||||
* memchr()
|
||||
/*
|
||||
* nbytes check because some systems (older FreeBSDs) have a
|
||||
* buggy memchr()
|
||||
*/
|
||||
if (nbytes && (dst = memchr(buf, '\0', nbytes))) {
|
||||
char *end = buf + nbytes;
|
||||
@ -1116,7 +1145,7 @@ ksh_get_wd(size_t *dlen)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Makes a filename into result using the following algorithm.
|
||||
* - make result NULL
|
||||
* - if file starts with '/', append file to result & set cdpathp to NULL
|
||||
@ -1133,7 +1162,8 @@ ksh_get_wd(size_t *dlen)
|
||||
*/
|
||||
int
|
||||
make_path(const char *cwd, const char *file,
|
||||
char **cdpathp, /* & of : separated list */
|
||||
/* & of : separated list */
|
||||
char **cdpathp,
|
||||
XString *xsp,
|
||||
int *phys_pathp)
|
||||
{
|
||||
@ -1218,7 +1248,8 @@ simplify_path(char *pathl)
|
||||
if ((isrooted = pathl[0] == '/'))
|
||||
very_start++;
|
||||
|
||||
/* Before After
|
||||
/*-
|
||||
* Before After
|
||||
* /foo/ /foo
|
||||
* /foo/../../bar /bar
|
||||
* /foo/./blah/.. /foo
|
||||
@ -1571,7 +1602,7 @@ unbksl(bool cstyle, int (*fg)(void), void (*fp)(int))
|
||||
/* FALLTHROUGH */
|
||||
case 'x':
|
||||
i = cstyle ? -1 : 2;
|
||||
/*
|
||||
/**
|
||||
* x: look for a hexadecimal number with up to
|
||||
* two (C style: arbitrary) digits; convert
|
||||
* to raw octet (C style: Unicode if >0xFF)
|
||||
|
24
mksh.1
24
mksh.1
@ -1,4 +1,4 @@
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.249 2011/02/11 00:41:35 tg Exp $
|
||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.250 2011/02/11 01:18:19 tg Exp $
|
||||
.\" $OpenBSD: ksh.1,v 1.138 2010/09/20 07:41:17 jmc Exp $
|
||||
.\"-
|
||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||
@ -162,6 +162,8 @@
|
||||
.Op Ar argument ...
|
||||
.Oc
|
||||
.Ek
|
||||
.Nm builtin-name
|
||||
.Op Ar argument ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a command interpreter intended for both interactive and shell
|
||||
@ -170,6 +172,9 @@ Its command language is a superset of the
|
||||
.Xr sh C
|
||||
shell language and largely compatible to the original Korn shell.
|
||||
.Pp
|
||||
Most builtins can be called directly, for example if a link points from its
|
||||
name to the shell; not all make sense, have been tested or work at all though.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl c Ar string
|
||||
@ -3176,8 +3181,8 @@ If the
|
||||
.Ic posix
|
||||
or
|
||||
.Ic sh
|
||||
option is set, only the first argument is treated as an option, and only
|
||||
if it is exactly
|
||||
option is set or this is a direct builtin call, only the first argument
|
||||
is treated as an option, and only if it is exactly
|
||||
.Dq Fl n .
|
||||
Backslash interpretation is disabled.
|
||||
.Pp
|
||||
@ -3865,7 +3870,9 @@ is used).
|
||||
Enable UTF-8 support in the
|
||||
.Sx Emacs editing mode
|
||||
and internal string handling functions.
|
||||
This is enabled automatically for interactive shells if your system supports
|
||||
This flag is disabled by default, but can be enabled by setting it on the
|
||||
shell command line; is enabled automatically for interactive shells if
|
||||
requested at compile time, your system supports
|
||||
.Fn setlocale LC_CTYPE \&""
|
||||
and optionally
|
||||
.Fn nl_langinfo CODESET ,
|
||||
@ -3878,8 +3885,10 @@ environment variables,
|
||||
and at least one of these returns something that matches
|
||||
.Dq UTF\-8
|
||||
or
|
||||
.Dq utf8 ,
|
||||
or if the input begins with a UTF-8 Byte Order Mark.
|
||||
.Dq utf8
|
||||
case-insensitively; for direct builtin calls depending on the
|
||||
aforementioned environment variables; or for stdin or scripts,
|
||||
if the input begins with a UTF-8 Byte Order Mark.
|
||||
.It Fl u \*(Ba Ic nounset
|
||||
Referencing of an unset parameter, other than
|
||||
.Dq $@
|
||||
@ -3904,7 +3913,7 @@ the value of
|
||||
.It Ic arc4random
|
||||
Deprecated, will be removed in
|
||||
.Nm
|
||||
R40.
|
||||
R41.
|
||||
Do not use, emits a warning to stderr.
|
||||
.It Ic bgnice
|
||||
Background jobs are run with lower priority.
|
||||
@ -4052,6 +4061,7 @@ Suspends execution for a minimum of the
|
||||
.Ar seconds
|
||||
specified as positive decimal value with an optional fractional part.
|
||||
Signal delivery may continue execution earlier.
|
||||
.Pp
|
||||
.It Ic source Ar file Op Ar arg ...
|
||||
Like
|
||||
.Ic \&. Po Do dot Dc Pc ,
|
||||
|
8
sh.h
8
sh.h
@ -154,9 +154,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.429 2011/02/11 00:41:37 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.430 2011/02/11 01:18:22 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R39 2011/02/09"
|
||||
#define MKSH_VERSION "R39 2011/02/11"
|
||||
|
||||
#ifndef MKSH_INCLUDES_ONLY
|
||||
|
||||
@ -1459,9 +1459,9 @@ int execute(struct op * volatile, volatile int, volatile int * volatile);
|
||||
int shcomexec(const char **);
|
||||
struct tbl *findfunc(const char *, uint32_t, bool);
|
||||
int define(const char *, struct op *);
|
||||
void builtin(const char *, int (*)(const char **));
|
||||
const char *builtin(const char *, int (*)(const char **));
|
||||
struct tbl *findcom(const char *, int);
|
||||
void flushcom(int);
|
||||
void flushcom(bool);
|
||||
const char *search(const char *, const char *, int, int *);
|
||||
int search_access(const char *, int, int *);
|
||||
int pr_menu(const char * const *);
|
||||
|
@ -1,5 +1,5 @@
|
||||
#if defined(SHFLAGS_DEFNS)
|
||||
__RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.7 2010/07/13 13:07:58 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.8 2011/02/11 01:18:23 tg Exp $");
|
||||
#define FN(sname,cname,ochar,flags) /* nothing */
|
||||
#elif defined(SHFLAGS_ENUMS)
|
||||
#define FN(sname,cname,ochar,flags) cname,
|
||||
@ -135,6 +135,9 @@ FN(NULL, FCOMMAND, 'c', OF_CMDLINE)
|
||||
* anonymous flags: used internally by shell only (not visible to user)
|
||||
*/
|
||||
|
||||
/* ./. direct builtin call (divined from argv[0] multi-call binary) */
|
||||
FN(NULL, FAS_BUILTIN, 0, OF_INTERNAL)
|
||||
|
||||
/* ./. (internal) initial shell was interactive */
|
||||
FN(NULL, FTALKING_I, 0, OF_INTERNAL)
|
||||
|
||||
|
8
var.c
8
var.c
@ -26,7 +26,7 @@
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.115 2011/01/21 21:04:48 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.116 2011/02/11 01:18:23 tg Exp $");
|
||||
|
||||
/*
|
||||
* Variables
|
||||
@ -1084,7 +1084,8 @@ setspec(struct tbl *vp)
|
||||
afree(path, APERM);
|
||||
s = str_val(vp);
|
||||
strdupx(path, s, APERM);
|
||||
flushcom(1); /* clear tracked aliases */
|
||||
/* clear tracked aliases */
|
||||
flushcom(true);
|
||||
return;
|
||||
case V_IFS:
|
||||
setctypes(s = str_val(vp), C_IFS);
|
||||
@ -1182,7 +1183,8 @@ unsetspec(struct tbl *vp)
|
||||
if (path)
|
||||
afree(path, APERM);
|
||||
strdupx(path, def_path, APERM);
|
||||
flushcom(1); /* clear tracked aliases */
|
||||
/* clear tracked aliases */
|
||||
flushcom(true);
|
||||
break;
|
||||
case V_IFS:
|
||||
setctypes(" \t\n", C_IFS);
|
||||
|
Loading…
x
Reference in New Issue
Block a user