summaryrefslogtreecommitdiff
path: root/usr/src/lib/libcmd/common/tee.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libcmd/common/tee.c')
-rw-r--r--usr/src/lib/libcmd/common/tee.c146
1 files changed, 86 insertions, 60 deletions
diff --git a/usr/src/lib/libcmd/common/tee.c b/usr/src/lib/libcmd/common/tee.c
index c1189bade7..246b5af9c3 100644
--- a/usr/src/lib/libcmd/common/tee.c
+++ b/usr/src/lib/libcmd/common/tee.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -27,7 +27,7 @@
*/
static const char usage[] =
-"[-?\n@(#)$Id: tee (AT&T Research) 2007-11-11 $\n]"
+"[-?\n@(#)$Id: tee (AT&T Research) 2009-06-19 $\n]"
USAGE_LICENSE
"[+NAME?tee - duplicate standard input]"
"[+DESCRIPTION?\btee\b copies standard input to standard output "
@@ -52,7 +52,6 @@ USAGE_LICENSE
"[+SEE ALSO?\bcat\b(1), \bsignal\b(3)]"
;
-
#include <cmd.h>
#include <ls.h>
#include <sig.h>
@@ -60,6 +59,7 @@ USAGE_LICENSE
typedef struct Tee_s
{
Sfdisc_t disc;
+ int line;
int fd[1];
} Tee_t;
@@ -67,7 +67,8 @@ typedef struct Tee_s
* This discipline writes to each file in the list given in handle
*/
-static ssize_t tee_write(Sfio_t* fp, const void* buf, size_t n, Sfdisc_t* handle)
+static ssize_t
+tee_write(Sfio_t* fp, const void* buf, size_t n, Sfdisc_t* handle)
{
register const char* bp;
register const char* ep;
@@ -82,11 +83,27 @@ static ssize_t tee_write(Sfio_t* fp, const void* buf, size_t n, Sfdisc_t* handle
while (bp < ep)
{
if ((r = write(fd, bp, ep - bp)) <= 0)
- return(-1);
+ return -1;
bp += r;
}
} while ((fd = *hp++) >= 0);
- return(n);
+ return n;
+}
+
+static void
+tee_cleanup(register Tee_t* tp)
+{
+ register int* hp;
+ register int n;
+
+ if (tp)
+ {
+ sfdisc(sfstdout, NiL);
+ if (tp->line >= 0)
+ sfset(sfstdout, SF_LINE, tp->line);
+ for (hp = tp->fd; (n = *hp) >= 0; hp++)
+ close(n);
+ }
}
int
@@ -100,32 +117,45 @@ b_tee(int argc, register char** argv, void* context)
int line;
Sfdisc_t tee_disc;
- cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ if (argc <= 0)
+ {
+ if (context && (tp = (Tee_t*)sh_context(context)->data))
+ {
+ sh_context(context)->data = 0;
+ tee_cleanup(tp);
+ }
+ return 0;
+ }
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_CALLBACK);
line = -1;
- while (n = optget(argv, usage)) switch (n)
+ for (;;)
{
- case 'a':
- oflag &= ~O_TRUNC;
- oflag |= O_APPEND;
- break;
- case 'i':
- signal(SIGINT, SIG_IGN);
- break;
- case 'l':
- line = sfset(sfstdout, 0, 0) & SF_LINE;
- if ((line == 0) == (opt_info.num == 0))
- line = -1;
- else
- sfset(sfstdout, SF_LINE, !!opt_info.num);
- break;
- case ':':
- error(2, "%s", opt_info.arg);
- break;
- case '?':
- error(ERROR_usage(2), "%s", opt_info.arg);
+ switch (optget(argv, usage))
+ {
+ case 'a':
+ oflag &= ~O_TRUNC;
+ oflag |= O_APPEND;
+ continue;
+ case 'i':
+ signal(SIGINT, SIG_IGN);
+ continue;
+ case 'l':
+ line = sfset(sfstdout, 0, 0) & SF_LINE;
+ if ((line == 0) == (opt_info.num == 0))
+ line = -1;
+ else
+ sfset(sfstdout, SF_LINE, !!opt_info.num);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
break;
}
- if(error_info.errors)
+ if (error_info.errors)
error(ERROR_usage(2), "%s", optusage(NiL));
argv += opt_info.index;
argc -= opt_info.index;
@@ -139,40 +169,36 @@ b_tee(int argc, register char** argv, void* context)
#endif
if (argc > 0)
{
- if (!(tp = (Tee_t*)stakalloc(sizeof(Tee_t) + argc * sizeof(int))))
- error(ERROR_exit(1), "no space");
- memset(&tee_disc, 0, sizeof(tee_disc));
- tee_disc.writef = tee_write;
- tp->disc = tee_disc;
- hp = tp->fd;
- while (cp = *argv++)
+ if (tp = (Tee_t*)stakalloc(sizeof(Tee_t) + argc * sizeof(int)))
{
- if ((*hp = open(cp, oflag, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
- error(ERROR_system(0), "%s: cannot create", cp);
- else hp++;
+ memset(&tp->disc, 0, sizeof(tp->disc));
+ tp->disc.writef = tee_write;
+ if (context)
+ sh_context(context)->data = (void*)tp;
+ tp->line = line;
+ hp = tp->fd;
+ while (cp = *argv++)
+ {
+ if ((*hp = open(cp, oflag, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
+ error(ERROR_system(0), "%s: cannot create", cp);
+ else
+ hp++;
+ }
+ if (hp == tp->fd)
+ tp = 0;
+ else
+ {
+ *hp = -1;
+ sfdisc(sfstdout, &tp->disc);
+ }
}
- if (hp == tp->fd)
- tp = 0;
else
- {
- *hp = -1;
- sfdisc(sfstdout, &tp->disc);
- }
- }
- if (sfmove(sfstdin, sfstdout, SF_UNBOUND, -1) < 0 || !sfeof(sfstdin) || sfsync(sfstdout))
- error(ERROR_system(1), "cannot copy");
-
- /*
- * close files and free resources
- */
-
- if (tp)
- {
- sfdisc(sfstdout, NiL);
- if (line >= 0)
- sfset(sfstdout, SF_LINE, line);
- for(hp = tp->fd; (n = *hp) >= 0; hp++)
- close(n);
+ error(ERROR_exit(0), "out of space");
}
- return(error_info.errors);
+ if ((sfmove(sfstdin, sfstdout, SF_UNBOUND, -1) < 0 || !sfeof(sfstdin)) && errno != EPIPE)
+ error(ERROR_system(0), "read error");
+ if (sfsync(sfstdout))
+ error(ERROR_system(0), "write error");
+ tee_cleanup(tp);
+ return error_info.errors;
}