make cat an mksh builtin, for things like here documents

if any options are given, the external programme is invoked instead
This commit is contained in:
tg 2010-08-28 17:21:46 +00:00
parent 297e2ced89
commit d09fd67299
5 changed files with 120 additions and 12 deletions

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.388 2010/08/24 15:47:44 tg Exp $
# $MirOS: src/bin/mksh/check.t,v 1.389 2010/08/28 17:21:41 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 2010/08/24
@(#)MIRBSD KSH R39 2010/08/28
description:
Check version of shell.
stdin:

17
exec.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.77 2010/08/28 15:48:18 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.78 2010/08/28 17:21:43 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
@ -489,6 +489,21 @@ comexec(struct op *t, struct tbl *volatile tp, const char **ap,
subst_exstat = 0;
break;
}
} else if (tp->val.f == c_cat) {
/*
* if we have any flags, do not use the builtin
* in theory, we could allow -u, but that would
* mean to use ksh_getopt here and possibly ad-
* ded complexity and more code and isn't worth
*/
if (ap[1] && ap[1][0] == '-' && ap[1][1] != '\0' &&
/* argument, begins with -, is not - or -- */
(ap[1][1] != '-' || ap[1][2] != '\0'))
/* don't look for builtins or functions */
fcflags = FC_PATH;
else
/* go on, use the builtin */
break;
} else
break;
tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC));

77
funcs.c
View File

@ -25,7 +25,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.157 2010/08/24 14:42:01 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.158 2010/08/28 17:21:44 tg Exp $");
#if HAVE_KILLPG
/*
@ -102,6 +102,7 @@ const struct builtin mkshbuiltins[] = {
{"+fg", c_fgbg},
#endif
{"bind", c_bind},
{"cat", c_cat},
#if HAVE_MKNOD
{"mknod", c_mknod},
#endif
@ -3427,3 +3428,77 @@ c_realpath(const char **wp)
return (rv);
}
int
c_cat(const char **wp)
{
int fd = STDIN_FILENO, rv = 0;
ssize_t n, w;
const char *fn = "<stdin>";
char *buf, *cp;
#define MKSH_CAT_BUFSIZ 4096
/* XXX uses malloc instead of lalloc (for alignment/speed) */
if ((buf = malloc(MKSH_CAT_BUFSIZ)) == NULL) {
bi_errorf("cannot allocate %lu data bytes",
(unsigned long)MKSH_CAT_BUFSIZ);
return (1);
}
++wp; /* argv[0] */
if (wp[0] && wp[0][0] == '-' && wp[0][1] == '-' && wp[0][2] == '\0')
++wp; /* "--" (options separator) */
do {
if (*wp) {
fn = *wp++;
if (fn[0] == '-' && fn[1] == '\0')
fd = STDIN_FILENO;
else if ((fd = open(fn, O_RDONLY)) < 0) {
rv = errno;
bi_errorf("%s: %s", fn, strerror(rv));
rv = 1;
continue;
}
}
while (1) {
n = blocking_read(fd, (cp = buf), MKSH_CAT_BUFSIZ);
if (n == -1) {
if (errno == EINTR)
/* interrupted, try again */
continue;
/* an error occured during reading */
rv = errno;
bi_errorf("%s: %s", fn, strerror(rv));
rv = 1;
break;
} else if (n == 0)
/* end of file reached */
break;
while (n) {
w = write(STDOUT_FILENO, cp, n);
if (w == -1) {
if (errno == EINTR)
/* interrupted, try again */
continue;
/* an error occured during writing */
rv = errno;
bi_errorf("%s: %s", "<stdout>",
strerror(rv));
rv = 1;
if (fd != STDIN_FILENO)
close(fd);
goto out;
}
n -= w;
cp += w;
}
}
if (fd != STDIN_FILENO)
close(fd);
} while (*wp);
out:
free(buf);
return (rv);
}

29
mksh.1
View File

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.235 2010/08/24 14:42:03 tg Exp $
.\" $MirOS: src/bin/mksh/mksh.1,v 1.236 2010/08/28 17:21:44 tg Exp $
.\" $OpenBSD: ksh.1,v 1.136 2010/07/15 20:04:35 schwarze Exp $
.\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
@ -71,7 +71,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always.
.\"
.Dd $Mdocdate: August 24 2010 $
.Dd $Mdocdate: August 28 2010 $
.\"
.\" Check which macro package we use
.\"
@ -2780,10 +2780,10 @@ Additional
.Nm
regular commands
.Pp
.Ic \&[ , chdir , bind , echo ,
.Ic let , mknod , print , printf ,
.Ic pwd , realpath , rename , test ,
.Ic ulimit , whence
.Ic \&[ , chdir , bind , cat ,
.Ic echo , let , mknod , print ,
.Ic printf , pwd , realpath , rename ,
.Ic test , ulimit , whence
.Pp
In the future, the additional
.Nm
@ -2963,6 +2963,22 @@ Execute the built-in command
.Ar command .
.Pp
.It Xo
.Ic cat
.Op Fl \-
.Op Ar
.Xc
Read files sequentially, in command line order, and write them to
standard output.
If
.Ar file
is a single dash
.Pq Sq -
or absent, read from standard input.
If any options are given, an external
.Xr cat 1
utility is invoked instead.
.Pp
.It Xo
.Ic cd
.Op Fl LP
.Op Ar dir
@ -5910,6 +5926,7 @@ Privileged shell profile.
.El
.Sh SEE ALSO
.Xr awk 1 ,
.Xr cat 1 ,
.Xr ed 1 ,
.Xr getopt 1 ,
.Xr sed 1 ,

5
sh.h
View File

@ -150,9 +150,9 @@
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.408 2010/08/28 16:47:10 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.409 2010/08/28 17:21:46 tg Exp $");
#endif
#define MKSH_VERSION "R39 2010/08/24"
#define MKSH_VERSION "R39 2010/08/28"
#ifndef MKSH_INCLUDES_ONLY
@ -1472,6 +1472,7 @@ int c_mknod(const char **);
#endif
int c_realpath(const char **);
int c_rename(const char **);
int c_cat(const char **);
/* histrap.c */
void init_histvec(void);
void hist_init(Source *);