From 35c32d4ba0f7406c857a277103474f203f8e4386 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 12 Aug 2016 17:29:25 -0600 Subject: [PATCH] apps/system/tee: Port tee command from NetBSD --- system/tee/.gitignore | 11 ++ system/tee/Kconfig | 26 +++++ system/tee/Make.defs | 39 +++++++ system/tee/Makefile | 146 +++++++++++++++++++++++++ system/tee/tee.c | 242 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 464 insertions(+) create mode 100644 system/tee/.gitignore create mode 100644 system/tee/Kconfig create mode 100644 system/tee/Make.defs create mode 100644 system/tee/Makefile create mode 100644 system/tee/tee.c diff --git a/system/tee/.gitignore b/system/tee/.gitignore new file mode 100644 index 000000000..83bd7b811 --- /dev/null +++ b/system/tee/.gitignore @@ -0,0 +1,11 @@ +/Make.dep +/.depend +/.built +/*.asm +/*.rel +/*.lst +/*.sym +/*.adb +/*.lib +/*.src +/*.obj diff --git a/system/tee/Kconfig b/system/tee/Kconfig new file mode 100644 index 000000000..22d394f9b --- /dev/null +++ b/system/tee/Kconfig @@ -0,0 +1,26 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config SYSTEM_TEE + bool "Tee Command" + default n + ---help--- + Enable support for the tee command. + +if SYSTEM_TEE + +config SYSTEM_TEE_STACKSIZE + int "tee stack size" + default 1536 + ---help--- + The size of stack allocated for the tee task. + +config SYSTEM_TEE_PRIORITY + int "tee priority" + default 100 + ---help--- + The priority of the tee task. + +endif diff --git a/system/tee/Make.defs b/system/tee/Make.defs new file mode 100644 index 000000000..9ff686e1a --- /dev/null +++ b/system/tee/Make.defs @@ -0,0 +1,39 @@ +############################################################################ +# apps/system/tee/Make.defs +# Adds selected applications to apps/ build +# +# Copyright (C) 2016 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifeq ($(CONFIG_SYSTEM_TEE),y) +CONFIGURED_APPS += system/tee +endif diff --git a/system/tee/Makefile b/system/tee/Makefile new file mode 100644 index 000000000..e73bbcb65 --- /dev/null +++ b/system/tee/Makefile @@ -0,0 +1,146 @@ +############################################################################ +# apps/system/tee/Makefile +# +# Copyright (C) 2011-2012 Uros Platise. All rights reserved. +# Copyright (C) 2012, 2016 Gregory Nutt. All rights reserved. +# Author: Uros Platise +# Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs +include $(APPDIR)/Make.defs + +# tee command + +CONFIG_SYSTEM_TEE_STACKSIZE ?= 1536 +CONFIG_SYSTEM_TEE_PRIORITY ?= 100 + +APPNAME = tee +PRIORITY = $(CONFIG_SYSTEM_TEE_PRIORITY) +STACKSIZE = $(CONFIG_SYSTEM_TEE_PRIORITY) + +ASRCS = +CSRCS = +MAINSRC = tee.c + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) +MAINOBJ = $(MAINSRC:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) $(MAINSRC) +OBJS = $(AOBJS) $(COBJS) + +ifneq ($(CONFIG_BUILD_KERNEL),y) + OBJS += $(MAINOBJ) +endif + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + BIN = ..\..\libapps$(LIBEXT) +else +ifeq ($(WINTOOL),y) + BIN = ..\\..\\libapps$(LIBEXT) +else + BIN = ../../libapps$(LIBEXT) +endif +endif + +ifeq ($(WINTOOL),y) + INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}" +else + INSTALL_DIR = $(BIN_DIR) +endif + +CONFIG_XYZ_PROGNAME ?= tee$(EXEEXT) +PROGNAME = $(CONFIG_XYZ_PROGNAME) + +ROOTDEPPATH = --dep-path . + +# Common build + +VPATH = + +all: .built +.PHONY: context depend clean distclean + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS) $(MAINOBJ): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +.built: $(OBJS) + $(call ARCHIVE, $(BIN), $(OBJS)) + $(Q) touch .built + +ifeq ($(CONFIG_BUILD_KERNEL),y) +$(BIN_DIR)$(DELIM)$(PROGNAME): $(OBJS) $(MAINOBJ) + @echo "LD: $(PROGNAME)" + $(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(PROGNAME) $(ARCHCRT0OBJ) $(MAINOBJ) $(LDLIBS) + $(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(PROGNAME) + +install: $(BIN_DIR)$(DELIM)$(PROGNAME) + +else +install: + +endif + +# Register application + +ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) +$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + +context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat +else +context: +endif + +# Create dependencies + +.depend: Makefile $(SRCS) + $(Q) $(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep + $(Q) touch $@ + +depend: .depend + +clean: + $(call DELFILE, .built) + $(call CLEAN) + +distclean: clean + $(call DELFILE, Make.dep) + $(call DELFILE, .depend) + +-include Make.dep +.PHONY: preconfig +preconfig: diff --git a/system/tee/tee.c b/system/tee/tee.c new file mode 100644 index 000000000..5aa5fbd9e --- /dev/null +++ b/system/tee/tee.c @@ -0,0 +1,242 @@ +/**************************************************************************** + * apps/system/tee/tee.c + * $NetBSD: tee.c,v 1.6 1997/10/20 00:37:11 lukem Exp $ + * + * Copyright (c) 2016. Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Leveraged from NetBSD: + * + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BSIZE 1024 +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct tee_list_s +{ + FAR struct tee_list_s *next; + FAR char *name; + int fd; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int tee_add(int fd, FAR char *name, + FAR struct tee_list_s **head) +{ + FAR struct tee_list_s *curr; + + curr = (FAR struct tee_list_s *)malloc((sizeof(struct tee_list_s))); + if (curr == NULL) + { + _err("ERROR: alloc failed\n"); + return -ENOMEM; + } + + curr->fd = fd; + curr->name = name; + curr->next = *head; + *head = curr; + + return OK; +} + +static void show_usage(FAR const char *progrname, int exitcode) +{ + fprintf(stderr, "USAGE: tee [-a] [file ...]\n"); + fprintf(stderr, " tee -h\n"); + fprintf(stderr, "Where:\n"); + fprintf(stderr, "-a:\n"); + fprintf(stderr, "\tAppend to the file (vs. truncating)\n"); + fprintf(stderr, "file:\n"); + fprintf(stderr, "\tArbitrary number of options output files. Output\n"); + fprintf(stderr, "\twill go to stdout in addition to each of these files.\n"); + fprintf(stderr, "-h:\n"); + fprintf(stderr, "\tShows this message and exits\n"); + exit(exitcode); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +int main(int argc, FAR char *argv[]) +#else +int tee_main(int argc, char *argv[]) +#endif +{ + FAR struct tee_list_s *head = NULL; + FAR struct tee_list_s *curr; + FAR struct tee_list_s *next; + FAR char *buf; + FAR char *bp; + bool append = false; + int exitcode = EXIT_FAILURE; + int rval; + int wval; + int ret; + int fd; + int ch; + int n; + + while ((ch = getopt(argc, argv, "ah")) != -1) + { + switch (ch) + { + case 'a': + append = true; + break; + + case 'h': + show_usage(argv[0], EXIT_SUCCESS); + + case '?': + default: + show_usage(argv[0], EXIT_FAILURE); + } + } + + argv += optind; + argc -= optind; + + buf = (FAR char *)malloc((size_t)BSIZE); + if (buf == NULL) + { + _err("ERROR: malloc failed\n"); + exit(EXIT_FAILURE); + } + + ret = tee_add(STDOUT_FILENO, "stdout", &head); + if (ret < 0) + { + _err("ERROR: tee_add failed: %d\n", ret); + goto errout_with_buf; + } + + for (; *argv; ++argv) + { + fd = open(*argv, append ? O_WRONLY | O_CREAT | O_APPEND : + O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) + { + _err("ERROR: tee_add failed: %d\n", errno); + goto errout_with_list; + } + else + { + ret = tee_add(fd, *argv, &head); + if (ret < 0) + { + _err("ERROR: tee_add failed: %d\n", ret); + goto errout_with_list; + } + } + } + + while ((rval = read(STDIN_FILENO, buf, BSIZE)) > 0) + { + for (curr = head; curr; curr = curr->next) + { + n = rval; + bp = buf; + + do + { + wval = write(curr->fd, bp, n); + if (wval < 0) + { + _err("ERROR: write to %s failed: %d\n", + curr->name, errno); + break; + } + + bp += wval; + n -= wval; + } + while (n > 0); + } + } + + if (rval >= 0) + { + exitcode = EXIT_SUCCESS; + } + else + { + _err("ERROR: read failed: %d\n", errno); + } + +errout_with_list: + for (curr = head; curr; curr = next) + { + next = curr->next; + (void)close(curr->fd); + free(curr); + } + +errout_with_buf: + free(buf); + exit(exitcode); +}