New functionality: assign here document to string variable directly,
without cat and temp files. Hacked in Lëtzebuerg ☺ This was the third try. Where to put this was not palpable… same for =(…)
This commit is contained in:
parent
b4948e430f
commit
230f59d064
45
check.t
45
check.t
@ -1,9 +1,9 @@
|
|||||||
# $MirOS: src/bin/mksh/check.t,v 1.397 2010/12/19 20:00:53 tg Exp $
|
# $MirOS: src/bin/mksh/check.t,v 1.398 2011/01/09 21:57:22 tg Exp $
|
||||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas 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: 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 $
|
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||||
#-
|
#-
|
||||||
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
||||||
# Thorsten Glaser <tg@mirbsd.org>
|
# Thorsten Glaser <tg@mirbsd.org>
|
||||||
#
|
#
|
||||||
# Provided that these terms and disclaimer and all copyright notices
|
# Provided that these terms and disclaimer and all copyright notices
|
||||||
@ -25,7 +25,7 @@
|
|||||||
# http://www.research.att.com/~gsf/public/ifs.sh
|
# http://www.research.att.com/~gsf/public/ifs.sh
|
||||||
|
|
||||||
expected-stdout:
|
expected-stdout:
|
||||||
@(#)MIRBSD KSH R39 2010/12/19
|
@(#)MIRBSD KSH R39 2011/01/08
|
||||||
description:
|
description:
|
||||||
Check version of shell.
|
Check version of shell.
|
||||||
stdin:
|
stdin:
|
||||||
@ -2007,6 +2007,45 @@ stdin:
|
|||||||
expected-stdout:
|
expected-stdout:
|
||||||
one
|
one
|
||||||
---
|
---
|
||||||
|
name: heredoc-10
|
||||||
|
description:
|
||||||
|
Check direct here document assignment
|
||||||
|
stdin:
|
||||||
|
x=u
|
||||||
|
va=<<EOF
|
||||||
|
=a $x \x40=
|
||||||
|
EOF
|
||||||
|
vb=<<'EOF'
|
||||||
|
=b $x \x40=
|
||||||
|
EOF
|
||||||
|
function foo {
|
||||||
|
vc=<<-EOF
|
||||||
|
=c $x \x40=
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
typeset -f foo
|
||||||
|
foo
|
||||||
|
# rather nonsensical, but…
|
||||||
|
vd=<<<"=d $x \x40="
|
||||||
|
ve=<<<'=e $x \x40='
|
||||||
|
vf=<<<$'=f $x \x40='
|
||||||
|
# now check
|
||||||
|
print -r -- "| va={$va} vb={$vb} vc={$vc} vd={$vd} ve={$ve} vf={$vf} |"
|
||||||
|
expected-stdout:
|
||||||
|
function foo {
|
||||||
|
vc= <<- EOF
|
||||||
|
=c $x \x40=
|
||||||
|
EOF
|
||||||
|
|
||||||
|
}
|
||||||
|
| va={=a u \x40=
|
||||||
|
} vb={=b $x \x40=
|
||||||
|
} vc={=c u \x40=
|
||||||
|
} vd={=d u \x40=
|
||||||
|
} ve={=e $x \x40=
|
||||||
|
} vf={=f $x @=
|
||||||
|
} |
|
||||||
|
---
|
||||||
name: heredoc-quoting-unsubst
|
name: heredoc-quoting-unsubst
|
||||||
description:
|
description:
|
||||||
Check for correct handling of quoted characters in
|
Check for correct handling of quoted characters in
|
||||||
|
167
exec.c
167
exec.c
@ -1,7 +1,7 @@
|
|||||||
/* $OpenBSD: exec.c,v 1.49 2009/01/29 23:27:26 jaredy Exp $ */
|
/* $OpenBSD: exec.c,v 1.49 2009/01/29 23:27:26 jaredy 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>
|
* Thorsten Glaser <tg@mirbsd.org>
|
||||||
*
|
*
|
||||||
* Provided that these terms and disclaimer and all copyright notices
|
* Provided that these terms and disclaimer and all copyright notices
|
||||||
@ -22,18 +22,18 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.83 2010/09/15 21:08:17 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.84 2011/01/09 21:57:25 tg Exp $");
|
||||||
|
|
||||||
#ifndef MKSH_DEFAULT_EXECSHELL
|
#ifndef MKSH_DEFAULT_EXECSHELL
|
||||||
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
|
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int comexec(struct op *, struct tbl *volatile, const char **,
|
static int comexec(struct op *, struct tbl * volatile, const char **,
|
||||||
int volatile, volatile int *);
|
int volatile, volatile int *);
|
||||||
static void scriptexec(struct op *, const char **) MKSH_A_NORETURN;
|
static void scriptexec(struct op *, const char **) MKSH_A_NORETURN;
|
||||||
static int call_builtin(struct tbl *, const char **);
|
static int call_builtin(struct tbl *, const char **);
|
||||||
static int iosetup(struct ioword *, struct tbl *);
|
static int iosetup(struct ioword *, struct tbl *);
|
||||||
static int herein(const char *, int);
|
static int herein(const char *, int, char **);
|
||||||
static const char *do_selectargs(const char **, bool);
|
static const char *do_selectargs(const char **, bool);
|
||||||
static Test_op dbteste_isa(Test_env *, Test_meta);
|
static Test_op dbteste_isa(Test_env *, Test_meta);
|
||||||
static const char *dbteste_getopnd(Test_env *, Test_op, bool);
|
static const char *dbteste_getopnd(Test_env *, Test_op, bool);
|
||||||
@ -43,7 +43,7 @@ static void dbteste_error(Test_env *, int, const char *);
|
|||||||
* execute command tree
|
* execute command tree
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
execute(struct op *volatile t,
|
execute(struct op * volatile t,
|
||||||
volatile int flags, /* if XEXEC don't fork */
|
volatile int flags, /* if XEXEC don't fork */
|
||||||
volatile int * volatile xerrok)
|
volatile int * volatile xerrok)
|
||||||
{
|
{
|
||||||
@ -52,9 +52,10 @@ execute(struct op *volatile t,
|
|||||||
int pv[2];
|
int pv[2];
|
||||||
const char ** volatile ap;
|
const char ** volatile ap;
|
||||||
char ** volatile up;
|
char ** volatile up;
|
||||||
const char *s, *cp;
|
const char *s, *ccp;
|
||||||
struct ioword **iowp;
|
struct ioword **iowp;
|
||||||
struct tbl *tp = NULL;
|
struct tbl *tp = NULL;
|
||||||
|
char *cp;
|
||||||
|
|
||||||
if (t == NULL)
|
if (t == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
@ -71,7 +72,48 @@ execute(struct op *volatile t,
|
|||||||
if (trap)
|
if (trap)
|
||||||
runtraps(0);
|
runtraps(0);
|
||||||
|
|
||||||
if (t->type == TCOM) {
|
if (t->type == TCOM /* we want to run an executable... */) {
|
||||||
|
/* check if this is 'var=<<EOF' */
|
||||||
|
if (
|
||||||
|
/* we have zero arguments, i.e. no programme to run */
|
||||||
|
t->args[0] == NULL &&
|
||||||
|
/* we have exactly one variable assignment */
|
||||||
|
t->vars[0] != NULL && t->vars[1] == NULL &&
|
||||||
|
/* we have exactly one I/O redirection */
|
||||||
|
t->ioact != NULL && t->ioact[0] != NULL &&
|
||||||
|
t->ioact[1] == NULL &&
|
||||||
|
/* of type "here document" (or "here string") */
|
||||||
|
(t->ioact[0]->flag & IOTYPE) == IOHERE &&
|
||||||
|
/* the variable assignment begins with a valid varname */
|
||||||
|
(ccp = skip_wdvarname(t->vars[0], true)) != t->vars[0] &&
|
||||||
|
/* and has no right-hand side (i.e. "varname=") */
|
||||||
|
ccp[0] == CHAR && ccp[1] == '=' && ccp[2] == EOS &&
|
||||||
|
/* plus we can have a here document content */
|
||||||
|
herein(t->ioact[0]->heredoc, t->ioact[0]->flag & IOEVAL,
|
||||||
|
&cp) == 0 && cp && *cp) {
|
||||||
|
char *sp = cp, *dp;
|
||||||
|
size_t n = ccp - t->vars[0] + 2, z;
|
||||||
|
|
||||||
|
/* drop redirection (will be garbage collected) */
|
||||||
|
t->ioact = NULL;
|
||||||
|
|
||||||
|
/* set variable to its expanded value */
|
||||||
|
z = strlen(cp) + 1;
|
||||||
|
if (notoktomul(z, 2) || notoktoadd(z * 2, n))
|
||||||
|
internal_errorf(T_oomem, (unsigned long)-1);
|
||||||
|
dp = alloc(z * 2 + n, ATEMP);
|
||||||
|
memcpy(dp, t->vars[0], n);
|
||||||
|
t->vars[0] = dp;
|
||||||
|
dp += n;
|
||||||
|
while (*sp) {
|
||||||
|
*dp++ = QCHAR;
|
||||||
|
*dp++ = *sp++;
|
||||||
|
}
|
||||||
|
*dp = EOS;
|
||||||
|
/* free the expanded value */
|
||||||
|
afree(cp, APERM);
|
||||||
|
}
|
||||||
|
|
||||||
/* Clear subst_exstat before argument expansion. Used by
|
/* Clear subst_exstat before argument expansion. Used by
|
||||||
* null commands (see comexec() and c_eval()) and by c_set().
|
* null commands (see comexec() and c_eval()) and by c_set().
|
||||||
*/
|
*/
|
||||||
@ -293,12 +335,12 @@ execute(struct op *volatile t,
|
|||||||
}
|
}
|
||||||
} else { /* TSELECT */
|
} else { /* TSELECT */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!(cp = do_selectargs(ap, is_first))) {
|
if (!(ccp = do_selectargs(ap, is_first))) {
|
||||||
rv = 1;
|
rv = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
is_first = false;
|
is_first = false;
|
||||||
setstr(global(t->str), cp, KSH_UNWIND_ERROR);
|
setstr(global(t->str), ccp, KSH_UNWIND_ERROR);
|
||||||
execute(t->left, flags & XERROK, xerrok);
|
execute(t->left, flags & XERROK, xerrok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -337,11 +379,11 @@ execute(struct op *volatile t,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TCASE:
|
case TCASE:
|
||||||
cp = evalstr(t->str, DOTILDE);
|
ccp = evalstr(t->str, DOTILDE);
|
||||||
for (t = t->left; t != NULL && t->type == TPAT; t = t->right)
|
for (t = t->left; t != NULL && t->type == TPAT; t = t->right)
|
||||||
for (ap = (const char **)t->vars; *ap; ap++)
|
for (ap = (const char **)t->vars; *ap; ap++)
|
||||||
if ((s = evalstr(*ap, DOTILDE|DOPAT)) &&
|
if ((s = evalstr(*ap, DOTILDE|DOPAT)) &&
|
||||||
gmatchx(cp, s, false))
|
gmatchx(ccp, s, false))
|
||||||
goto Found;
|
goto Found;
|
||||||
break;
|
break;
|
||||||
Found:
|
Found:
|
||||||
@ -400,7 +442,7 @@ execute(struct op *volatile t,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
comexec(struct op *t, struct tbl *volatile tp, const char **ap,
|
comexec(struct op *t, struct tbl * volatile tp, const char **ap,
|
||||||
volatile int flags, volatile int *xerrok)
|
volatile int flags, volatile int *xerrok)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -566,7 +608,7 @@ comexec(struct op *t, struct tbl *volatile tp, const char **ap,
|
|||||||
case CFUNC: { /* function call */
|
case CFUNC: { /* function call */
|
||||||
volatile unsigned char old_xflag;
|
volatile unsigned char old_xflag;
|
||||||
volatile Tflag old_inuse;
|
volatile Tflag old_inuse;
|
||||||
const char *volatile old_kshname;
|
const char * volatile old_kshname;
|
||||||
|
|
||||||
if (!(tp->flag & ISSET)) {
|
if (!(tp->flag & ISSET)) {
|
||||||
struct tbl *ftp;
|
struct tbl *ftp;
|
||||||
@ -1171,7 +1213,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
case IOHERE:
|
case IOHERE:
|
||||||
do_open = 0;
|
do_open = 0;
|
||||||
/* herein() returns -2 if error has been printed */
|
/* herein() returns -2 if error has been printed */
|
||||||
u = herein(iop->heredoc, iop->flag & IOEVAL);
|
u = herein(iop->heredoc, iop->flag & IOEVAL, NULL);
|
||||||
/* cp may have wrong name */
|
/* cp may have wrong name */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1261,66 +1303,91 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* open here document temp file.
|
* Process here documents by providing the content, either as
|
||||||
* if unquoted here, expand here temp file into second temp file.
|
* result (globally allocated) string or in a temp file; if
|
||||||
|
* unquoted, the string is expanded first.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
herein(const char *content, int sub)
|
hereinval(const char *content, int sub, char **resbuf, struct shf *shf)
|
||||||
{
|
{
|
||||||
volatile int fd = -1;
|
const char *ccp;
|
||||||
struct source *s, *volatile osource;
|
struct source *s, *osource;
|
||||||
struct shf *volatile shf;
|
|
||||||
struct temp *h;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* ksh -c 'cat << EOF' can cause this... */
|
|
||||||
if (content == NULL) {
|
|
||||||
warningf(true, "%s missing", "here document");
|
|
||||||
return (-2); /* special to iosetup(): don't print error */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create temp file to hold content (done before newenv so temp
|
|
||||||
* doesn't get removed too soon).
|
|
||||||
*/
|
|
||||||
h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
|
|
||||||
if (!(shf = h->shf) || (fd = open(h->name, O_RDONLY, 0)) < 0) {
|
|
||||||
fd = errno;
|
|
||||||
warningf(true, "can't %s temporary file %s: %s",
|
|
||||||
!shf ? "create" : "open",
|
|
||||||
h->name, strerror(fd));
|
|
||||||
if (shf)
|
|
||||||
shf_close(shf);
|
|
||||||
return (-2 /* special to iosetup(): don't print error */);
|
|
||||||
}
|
|
||||||
|
|
||||||
osource = source;
|
osource = source;
|
||||||
newenv(E_ERRH);
|
newenv(E_ERRH);
|
||||||
i = sigsetjmp(e->jbuf, 0);
|
if (sigsetjmp(e->jbuf, 0)) {
|
||||||
if (i) {
|
|
||||||
source = osource;
|
source = osource;
|
||||||
quitenv(shf);
|
quitenv(shf);
|
||||||
close(fd);
|
/* special to iosetup(): don't print error */
|
||||||
return (-2); /* special to iosetup(): don't print error */
|
return (-2);
|
||||||
}
|
}
|
||||||
if (sub) {
|
if (sub) {
|
||||||
/* Do substitutions on the content of heredoc */
|
/* do substitutions on the content of heredoc */
|
||||||
s = pushs(SSTRING, ATEMP);
|
s = pushs(SSTRING, ATEMP);
|
||||||
s->start = s->str = content;
|
s->start = s->str = content;
|
||||||
source = s;
|
source = s;
|
||||||
if (yylex(ONEWORD|HEREDOC) != LWORD)
|
if (yylex(ONEWORD|HEREDOC) != LWORD)
|
||||||
internal_errorf("%s: %s", "herein", "yylex");
|
internal_errorf("%s: %s", "herein", "yylex");
|
||||||
source = osource;
|
source = osource;
|
||||||
shf_puts(evalstr(yylval.cp, 0), shf);
|
ccp = evalstr(yylval.cp, 0);
|
||||||
} else
|
} else
|
||||||
shf_puts(content, shf);
|
ccp = content;
|
||||||
|
|
||||||
|
if (resbuf == NULL)
|
||||||
|
shf_puts(ccp, shf);
|
||||||
|
else
|
||||||
|
strdupx(*resbuf, ccp, APERM);
|
||||||
|
|
||||||
quitenv(NULL);
|
quitenv(NULL);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
herein(const char *content, int sub, char **resbuf)
|
||||||
|
{
|
||||||
|
int fd = -1;
|
||||||
|
struct shf *shf;
|
||||||
|
struct temp *h;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* ksh -c 'cat << EOF' can cause this... */
|
||||||
|
if (content == NULL) {
|
||||||
|
warningf(true, "%s missing", "here document");
|
||||||
|
/* special to iosetup(): don't print error */
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip all the fd setup if we just want the value */
|
||||||
|
if (resbuf != NULL)
|
||||||
|
return (hereinval(content, sub, resbuf, NULL));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create temp file to hold content (done before newenv
|
||||||
|
* so temp doesn't get removed too soon).
|
||||||
|
*/
|
||||||
|
h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
|
||||||
|
if (!(shf = h->shf) || (fd = open(h->name, O_RDONLY, 0)) < 0) {
|
||||||
|
i = errno;
|
||||||
|
warningf(true, "can't %s temporary file %s: %s",
|
||||||
|
!shf ? "create" : "open", h->name, strerror(i));
|
||||||
|
if (shf)
|
||||||
|
shf_close(shf);
|
||||||
|
/* special to iosetup(): don't print error */
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hereinval(content, sub, NULL, shf) == -2) {
|
||||||
|
close(fd);
|
||||||
|
/* special to iosetup(): don't print error */
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
|
||||||
if (shf_close(shf) == EOF) {
|
if (shf_close(shf) == EOF) {
|
||||||
i = errno;
|
i = errno;
|
||||||
close(fd);
|
close(fd);
|
||||||
warningf(true, "%s: %s: %s", "write", h->name, strerror(i));
|
warningf(true, "%s: %s: %s", "write", h->name, strerror(i));
|
||||||
return (-2); /* special to iosetup(): don't print error */
|
/* special to iosetup(): don't print error */
|
||||||
|
return (-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (fd);
|
return (fd);
|
||||||
|
14
funcs.c
14
funcs.c
@ -4,7 +4,8 @@
|
|||||||
/* $OpenBSD: c_ulimit.c,v 1.17 2008/03/21 12:51:19 millert Exp $ */
|
/* $OpenBSD: c_ulimit.c,v 1.17 2008/03/21 12:51:19 millert Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||||
|
* 2010, 2011
|
||||||
* Thorsten Glaser <tg@mirbsd.org>
|
* Thorsten Glaser <tg@mirbsd.org>
|
||||||
*
|
*
|
||||||
* Provided that these terms and disclaimer and all copyright notices
|
* Provided that these terms and disclaimer and all copyright notices
|
||||||
@ -25,7 +26,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.164 2010/11/01 17:29:02 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.165 2011/01/09 21:57:26 tg Exp $");
|
||||||
|
|
||||||
#if HAVE_KILLPG
|
#if HAVE_KILLPG
|
||||||
/*
|
/*
|
||||||
@ -1174,8 +1175,10 @@ c_typeset(const char **wp)
|
|||||||
char *s = str_val(vp);
|
char *s = str_val(vp);
|
||||||
|
|
||||||
shf_putc('=', shl_stdout);
|
shf_putc('=', shl_stdout);
|
||||||
/* AT&T ksh can't have
|
/*
|
||||||
* justified integers.. */
|
* AT&T ksh can't have
|
||||||
|
* justified integers...
|
||||||
|
*/
|
||||||
if ((vp->flag &
|
if ((vp->flag &
|
||||||
(INTEGER|LJUST|RJUST)) ==
|
(INTEGER|LJUST|RJUST)) ==
|
||||||
INTEGER)
|
INTEGER)
|
||||||
@ -3464,8 +3467,7 @@ c_cat(const char **wp)
|
|||||||
|
|
||||||
/* XXX uses malloc instead of lalloc (for alignment/speed) */
|
/* XXX uses malloc instead of lalloc (for alignment/speed) */
|
||||||
if ((buf = malloc(MKSH_CAT_BUFSIZ)) == NULL) {
|
if ((buf = malloc(MKSH_CAT_BUFSIZ)) == NULL) {
|
||||||
bi_errorf("can't allocate %lu data bytes",
|
bi_errorf(T_oomem, (unsigned long)MKSH_CAT_BUFSIZ);
|
||||||
(unsigned long)MKSH_CAT_BUFSIZ);
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
9
lalloc.c
9
lalloc.c
@ -1,5 +1,5 @@
|
|||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2009, 2010
|
* Copyright (c) 2009, 2010, 2011
|
||||||
* Thorsten Glaser <tg@mirbsd.org>
|
* Thorsten Glaser <tg@mirbsd.org>
|
||||||
*
|
*
|
||||||
* Provided that these terms and disclaimer and all copyright notices
|
* Provided that these terms and disclaimer and all copyright notices
|
||||||
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.13 2010/09/14 21:26:14 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.14 2011/01/09 21:57:27 tg Exp $");
|
||||||
|
|
||||||
/* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */
|
/* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */
|
||||||
#if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0)
|
#if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0)
|
||||||
@ -70,7 +70,7 @@ findptr(ALLOC_ITEM **lpp, char *ptr, Area *ap)
|
|||||||
void *
|
void *
|
||||||
aresize2(void *ptr, size_t fac1, size_t fac2, Area *ap)
|
aresize2(void *ptr, size_t fac1, size_t fac2, Area *ap)
|
||||||
{
|
{
|
||||||
if (fac1 && fac2 && (SIZE_MAX / fac1 < fac2))
|
if (notoktomul(fac1, fac2))
|
||||||
internal_errorf(T_intovfl, (unsigned long)fac1, '*',
|
internal_errorf(T_intovfl, (unsigned long)fac1, '*',
|
||||||
(unsigned long)fac2);
|
(unsigned long)fac2);
|
||||||
return (aresize(ptr, fac1 * fac2, ap));
|
return (aresize(ptr, fac1 * fac2, ap));
|
||||||
@ -95,8 +95,7 @@ aresize(void *ptr, size_t numb, Area *ap)
|
|||||||
|| ALLOC_ISUNALIGNED(lp)
|
|| ALLOC_ISUNALIGNED(lp)
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
internal_errorf("can't allocate %lu data bytes",
|
internal_errorf(T_oomem, (unsigned long)numb);
|
||||||
(unsigned long)numb);
|
|
||||||
/* this only works because Area is an ALLOC_ITEM */
|
/* this only works because Area is an ALLOC_ITEM */
|
||||||
lp->next = ap->next;
|
lp->next = ap->next;
|
||||||
ap->next = lp;
|
ap->next = lp;
|
||||||
|
22
misc.c
22
misc.c
@ -2,7 +2,7 @@
|
|||||||
/* $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $ */
|
/* $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt 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>
|
* Thorsten Glaser <tg@mirbsd.org>
|
||||||
*
|
*
|
||||||
* Provided that these terms and disclaimer and all copyright notices
|
* Provided that these terms and disclaimer and all copyright notices
|
||||||
@ -29,7 +29,7 @@
|
|||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.148 2010/09/19 19:28:22 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.149 2011/01/09 21:57:27 tg Exp $");
|
||||||
|
|
||||||
unsigned char chtypes[UCHAR_MAX + 1]; /* type bits for unsigned char */
|
unsigned char chtypes[UCHAR_MAX + 1]; /* type bits for unsigned char */
|
||||||
|
|
||||||
@ -921,25 +921,33 @@ void
|
|||||||
print_value_quoted(const char *s)
|
print_value_quoted(const char *s)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
int inquote = 0;
|
bool inquote = false;
|
||||||
|
|
||||||
/* Test if any quotes are needed */
|
/* first, check whether any quotes are needed */
|
||||||
for (p = s; *p; p++)
|
for (p = s; *p; p++)
|
||||||
if (ctype(*p, C_QUOTE))
|
if (ctype(*p, C_QUOTE))
|
||||||
break;
|
break;
|
||||||
if (!*p) {
|
if (!*p) {
|
||||||
|
/* nope, use the shortcut */
|
||||||
shf_puts(s, shl_stdout);
|
shf_puts(s, shl_stdout);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* quote via state machine */
|
||||||
for (p = s; *p; p++) {
|
for (p = s; *p; p++) {
|
||||||
if (*p == '\'') {
|
if (*p == '\'') {
|
||||||
if (inquote)
|
/*
|
||||||
|
* multiple '''s or any ' at beginning of string
|
||||||
|
* look nicer this way than when simply substituting
|
||||||
|
*/
|
||||||
|
if (inquote) {
|
||||||
shf_putc('\'', shl_stdout);
|
shf_putc('\'', shl_stdout);
|
||||||
|
inquote = false;
|
||||||
|
}
|
||||||
shf_putc('\\', shl_stdout);
|
shf_putc('\\', shl_stdout);
|
||||||
inquote = 0;
|
|
||||||
} else if (!inquote) {
|
} else if (!inquote) {
|
||||||
shf_putc('\'', shl_stdout);
|
shf_putc('\'', shl_stdout);
|
||||||
inquote = 1;
|
inquote = true;
|
||||||
}
|
}
|
||||||
shf_putc(*p, shl_stdout);
|
shf_putc(*p, shl_stdout);
|
||||||
}
|
}
|
||||||
|
14
mksh.1
14
mksh.1
@ -1,7 +1,8 @@
|
|||||||
.\" $MirOS: src/bin/mksh/mksh.1,v 1.243 2010/12/19 20:00:55 tg Exp $
|
.\" $MirOS: src/bin/mksh/mksh.1,v 1.244 2011/01/09 21:57:27 tg Exp $
|
||||||
.\" $OpenBSD: ksh.1,v 1.138 2010/09/20 07:41:17 jmc Exp $
|
.\" $OpenBSD: ksh.1,v 1.138 2010/09/20 07:41:17 jmc Exp $
|
||||||
.\"-
|
.\"-
|
||||||
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||||
|
.\" 2010, 2011
|
||||||
.\" Thorsten Glaser <tg@mirbsd.org>
|
.\" Thorsten Glaser <tg@mirbsd.org>
|
||||||
.\"
|
.\"
|
||||||
.\" Provided that these terms and disclaimer and all copyright notices
|
.\" Provided that these terms and disclaimer and all copyright notices
|
||||||
@ -71,7 +72,7 @@
|
|||||||
.\" with -mandoc, it might implement .Mx itself, but we want to
|
.\" with -mandoc, it might implement .Mx itself, but we want to
|
||||||
.\" use our own definition. And .Dd must come *first*, always.
|
.\" use our own definition. And .Dd must come *first*, always.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: December 19 2010 $
|
.Dd $Mdocdate: January 9 2011 $
|
||||||
.\"
|
.\"
|
||||||
.\" Check which macro package we use
|
.\" Check which macro package we use
|
||||||
.\"
|
.\"
|
||||||
@ -6073,7 +6074,14 @@ code fails because of the parenthesis asymmetry
|
|||||||
.Pq RedHat BZ#496791 .
|
.Pq RedHat BZ#496791 .
|
||||||
A workaround exists; use
|
A workaround exists; use
|
||||||
.Ql x=$(cat) \*(Lt\*(Lt"EOF"
|
.Ql x=$(cat) \*(Lt\*(Lt"EOF"
|
||||||
|
or the newline-keeping
|
||||||
|
.Ql x=\*(Lt\*(Lt"EOF"
|
||||||
instead to merely slurp the string.
|
instead to merely slurp the string.
|
||||||
|
Of course, in this case, the form
|
||||||
|
.Ql x=$(case $foo in (bar) ...
|
||||||
|
actually recommended by
|
||||||
|
.St -p1003.1
|
||||||
|
would work as well, but we use it as an example of this parser bug.
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
x=$(case $foo in bar) echo $bar ;; *) echo $baz ;; esac)
|
x=$(case $foo in bar) echo $bar ;; *) echo $baz ;; esac)
|
||||||
# above fails to parse; below is the workaround
|
# above fails to parse; below is the workaround
|
||||||
|
12
sh.h
12
sh.h
@ -9,7 +9,7 @@
|
|||||||
/* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */
|
/* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto 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>
|
* Thorsten Glaser <tg@mirbsd.org>
|
||||||
*
|
*
|
||||||
* Provided that these terms and disclaimer and all copyright notices
|
* Provided that these terms and disclaimer and all copyright notices
|
||||||
@ -154,9 +154,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EXTERN
|
#ifdef EXTERN
|
||||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.420 2010/12/19 20:00:56 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.421 2011/01/09 21:57:29 tg Exp $");
|
||||||
#endif
|
#endif
|
||||||
#define MKSH_VERSION "R39 2010/12/19"
|
#define MKSH_VERSION "R39 2011/01/08"
|
||||||
|
|
||||||
#ifndef MKSH_INCLUDES_ONLY
|
#ifndef MKSH_INCLUDES_ONLY
|
||||||
|
|
||||||
@ -630,6 +630,7 @@ extern const struct shoption options[];
|
|||||||
EXTERN char null[] I__("");
|
EXTERN char null[] I__("");
|
||||||
/* helpers for string pooling */
|
/* helpers for string pooling */
|
||||||
EXTERN const char T_intovfl[] I__("integer overflow %lu %c %lu prevented");
|
EXTERN const char T_intovfl[] I__("integer overflow %lu %c %lu prevented");
|
||||||
|
EXTERN const char T_oomem[] I__("can't allocate %lu data bytes");
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
/* trust this to have string pooling; -Wformat bitches otherwise */
|
/* trust this to have string pooling; -Wformat bitches otherwise */
|
||||||
#define T_synerr "syntax error"
|
#define T_synerr "syntax error"
|
||||||
@ -1199,7 +1200,7 @@ struct ioword {
|
|||||||
#define DB_BE 4 /* an inserted -BE */
|
#define DB_BE 4 /* an inserted -BE */
|
||||||
#define DB_PAT 5 /* a pattern argument */
|
#define DB_PAT 5 /* a pattern argument */
|
||||||
|
|
||||||
#define X_EXTRA 8 /* this many extra bytes in X string */
|
#define X_EXTRA 20 /* this many extra bytes in X string */
|
||||||
|
|
||||||
typedef struct XString {
|
typedef struct XString {
|
||||||
char *end, *beg; /* end, begin of string */
|
char *end, *beg; /* end, begin of string */
|
||||||
@ -1397,6 +1398,8 @@ EXTERN int histsize; /* history size */
|
|||||||
/* user and system time of last j_waitjed job */
|
/* user and system time of last j_waitjed job */
|
||||||
EXTERN struct timeval j_usrtime, j_systime;
|
EXTERN struct timeval j_usrtime, j_systime;
|
||||||
|
|
||||||
|
#define notoktomul(fac1, fac2) ((fac1) && (fac2) && \
|
||||||
|
(SIZE_MAX / (fac1) < (fac2)))
|
||||||
#define notoktoadd(val, cnst) ((val) > (SIZE_MAX - (cnst)))
|
#define notoktoadd(val, cnst) ((val) > (SIZE_MAX - (cnst)))
|
||||||
#define checkoktoadd(val, cnst) do { \
|
#define checkoktoadd(val, cnst) do { \
|
||||||
if (notoktoadd((val), (cnst))) \
|
if (notoktoadd((val), (cnst))) \
|
||||||
@ -1637,6 +1640,7 @@ int xstrcmp(const void *, const void *);
|
|||||||
void ksh_getopt_reset(Getopt *, int);
|
void ksh_getopt_reset(Getopt *, int);
|
||||||
int ksh_getopt(const char **, Getopt *, const char *);
|
int ksh_getopt(const char **, Getopt *, const char *);
|
||||||
void print_value_quoted(const char *);
|
void print_value_quoted(const char *);
|
||||||
|
char *quote_value(const char *);
|
||||||
void print_columns(struct shf *, int,
|
void print_columns(struct shf *, int,
|
||||||
char *(*)(char *, int, int, const void *),
|
char *(*)(char *, int, int, const void *),
|
||||||
const void *, int, int, bool);
|
const void *, int, int, bool);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user