[BusyBox] Does anyone need 'tac' command?

Yang Xiaopeng yxp at hanwang.com.cn
Wed Jul 30 18:51:24 MDT 2003


hi,

I write a ugly 'tac' applet for busybox, it's very simple, just print 
input file lines in reverse, hope it could be helpful.

-------------- next part --------------
diff -urN busybox-1.00-pre1/coreutils/Config.in busybox-1.00/coreutils/Config.in
--- busybox-1.00-pre1/coreutils/Config.in	2003-07-15 03:37:08.000000000 +0800
+++ busybox-1.00/coreutils/Config.in	2003-07-30 17:33:04.000000000 +0800
@@ -421,6 +421,12 @@
 	help
 	  sync is used to flush filesystem buffers.
 
+config CONFIG_TAC
+	bool "tac"
+	default n
+	help
+	  tac is used to concatenate and print files in reverse.
+
 config CONFIG_TAIL
 	bool "tail"
 	default n
diff -urN busybox-1.00-pre1/coreutils/Makefile.in busybox-1.00/coreutils/Makefile.in
--- busybox-1.00-pre1/coreutils/Makefile.in	2003-07-15 05:20:43.000000000 +0800
+++ busybox-1.00/coreutils/Makefile.in	2003-07-30 17:33:05.000000000 +0800
@@ -67,6 +67,7 @@
 COREUTILS-$(CONFIG_SORT)	+= sort.o
 COREUTILS-$(CONFIG_STTY)		+= stty.o
 COREUTILS-$(CONFIG_SYNC)	+= sync.o
+COREUTILS-$(CONFIG_TAC)		+= tac.o
 COREUTILS-$(CONFIG_TAIL)	+= tail.o
 COREUTILS-$(CONFIG_TEE)		+= tee.o
 COREUTILS-$(CONFIG_TEST)		+= test.o
diff -urN busybox-1.00-pre1/coreutils/tac.c busybox-1.00/coreutils/tac.c
--- busybox-1.00-pre1/coreutils/tac.c	1970-01-01 08:00:00.000000000 +0800
+++ busybox-1.00/coreutils/tac.c	2003-07-30 17:33:05.000000000 +0800
@@ -0,0 +1,140 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * tac implementation for busybox
+ *
+ * Copyright (C) 2003  Yang Xiaopeng  <yxp at hanwang.com.cn>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* tac - concatenate and print files in reverse */
+
+/* Writen by Yang Xiaopeng (yxp at hanwang.com.cn), refer to the tac 
+ * source code Written by Jay Lepreau (lepreau at cs.utah.edu). */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include "busybox.h"
+
+#ifndef DEFAULT_TMPDIR
+#define DEFAULT_TMPDIR "/tmp"
+#endif
+
+/* Print file to stdout in reverse */
+static int tac_file(int fd)
+{
+	struct stat stats;
+	char *map, *ptr, *end;
+
+	if (fstat(fd, &stats)) {
+		return -1;
+	}
+
+	map = mmap(0, stats.st_size, PROT_READ, MAP_SHARED, fd, 0);
+	if (map == MAP_FAILED) {
+		return -1;
+	}
+
+	ptr = end = map + stats.st_size - 1;
+	while (ptr >= map) {
+		if (*ptr == '\n') ptr--;
+		while (ptr >= map && *ptr != '\n') ptr--;
+		bb_full_write(STDOUT_FILENO, ptr+1, end-ptr);
+		end = ptr;
+	}
+	munmap(map, stats.st_size);
+	
+	return 0;
+}
+
+/* Make a copy of the standard input. */
+static int save_stdin(int fdin)
+{
+	static char *template = NULL;
+	static char *tempdir;
+	int fd;
+
+	tempdir = getenv("TMPDIR");
+	if (!tempdir)
+		tempdir = DEFAULT_TMPDIR;
+	template = xmalloc(strlen(tempdir) + 11);
+	sprintf(template, "%s/tacXXXXXX", tempdir);
+
+	fd = mkstemp(template);
+	if (fd == -1) {
+		bb_error_msg("Can't creat temp file\n");
+		return -1;
+	}
+
+	if (bb_copyfd(fdin, fd, 0) < 0) {
+		bb_error_msg("Copy file error\n");
+		return -1;
+	}
+
+	unlink(template);
+	free(template);
+
+	return fd;
+}
+
+extern int tac_main(int argc, char **argv)
+{
+	FILE *f;
+	int retval = EXIT_SUCCESS;
+	struct stat stats;
+	int fd;
+	int error;
+
+	argv++;
+	if (!*argv)
+		*--argv = "-";
+
+	do {
+		if ((f = bb_wfopen_input(*argv)) != NULL) {
+			fd = fileno(f);
+			if (fstat(fd, &stats)) {
+				bb_error_msg("Can't stat input file\n");
+				retval = EXIT_FAILURE;
+				break;
+			}
+
+			if (S_ISREG(stats.st_mode)) {
+				error = tac_file(fd);
+			} else {
+				fd = save_stdin(fd);
+				if (fd == -1) {
+					retval = EXIT_FAILURE;
+					break;
+				}
+
+				error = tac_file(fd);
+				close(fd);
+			}
+
+			bb_fclose_nonstdin(f);
+
+			if (!error) {
+				continue;
+			}
+		}
+		retval = EXIT_FAILURE;
+	} while (*++argv);
+
+	return retval;
+}
diff -urN busybox-1.00-pre1/include/applets.h busybox-1.00/include/applets.h
--- busybox-1.00-pre1/include/applets.h	2003-07-05 15:51:31.000000000 +0800
+++ busybox-1.00/include/applets.h	2003-07-30 17:33:20.000000000 +0800
@@ -544,6 +544,9 @@
 #ifdef CONFIG_SYSLOGD
 	APPLET(syslogd, syslogd_main, _BB_DIR_SBIN, _BB_SUID_NEVER)
 #endif
+#ifdef CONFIG_TAC
+	APPLET(tac, tac_main, _BB_DIR_BIN, _BB_SUID_NEVER)
+#endif
 #ifdef CONFIG_TAIL
 	APPLET(tail, tail_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER)
 #endif
diff -urN busybox-1.00-pre1/include/usage.h busybox-1.00/include/usage.h
--- busybox-1.00-pre1/include/usage.h	2003-07-15 06:14:49.000000000 +0800
+++ busybox-1.00/include/usage.h	2003-07-30 17:33:20.000000000 +0800
@@ -2112,6 +2112,10 @@
 	"$ syslogd -R masterlog:514\n" \
 	"$ syslogd -R 192.168.1.1:601\n"
 
+#define tac_trivial_usage \
+	"[FILE]..."
+#define tac_full_usage \
+	"Concatenates FILE(s) and prints them to stdout in reverse.\n\n"
 
 #ifndef CONFIG_FEATURE_FANCY_TAIL
   #define USAGE_UNSIMPLE_TAIL(a)


More information about the busybox mailing list