From d09fd67299f8cca7c866082793841ab9e2237b28 Mon Sep 17 00:00:00 2001 From: tg Date: Sat, 28 Aug 2010 17:21:46 +0000 Subject: [PATCH] make cat an mksh builtin, for things like here documents if any options are given, the external programme is invoked instead --- check.t | 4 +-- exec.c | 17 ++++++++++++- funcs.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- mksh.1 | 29 +++++++++++++++++----- sh.h | 5 ++-- 5 files changed, 120 insertions(+), 12 deletions(-) diff --git a/check.t b/check.t index 494f66a..2a0df55 100644 --- a/check.t +++ b/check.t @@ -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: diff --git a/exec.c b/exec.c index 66e9bbf..fd12eeb 100644 --- a/exec.c +++ b/exec.c @@ -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)); diff --git a/funcs.c b/funcs.c index 9d9c03a..606aa51 100644 --- a/funcs.c +++ b/funcs.c @@ -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 = ""; + 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", "", + 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); +} diff --git a/mksh.1 b/mksh.1 index 74ef458..5ea8962 100644 --- a/mksh.1 +++ b/mksh.1 @@ -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 , diff --git a/sh.h b/sh.h index b598b1e..e00f17c 100644 --- a/sh.h +++ b/sh.h @@ -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 *);