blob: b1b47302f8e912ca48a03d3d5e2a65a10f5a99de [file] [log] [blame]
Denis Vlasenko482f2b32008-01-07 16:14:14 +00001/* vi: set sw=4 ts=4: */
2/*
3 * tac implementation for busybox
4 *
5 * Copyright (C) 2003 Yang Xiaopeng <yxp at hanwang.com.cn>
6 * Copyright (C) 2007 Natanael Copa <natanael.copa@gmail.com>
7 * Copyright (C) 2007 Tito Ragusa <farmatito@tiscali.it>
8 *
9 * Licensed under GPLv2, see file License in this tarball for details.
10 *
11 */
12
13/* tac - concatenate and print files in reverse */
14
15/* Based on Yang Xiaopeng's (yxp at hanwang.com.cn) patch
16 * http://www.uclibc.org/lists/busybox/2003-July/008813.html
17 */
18
19#include "libbb.h"
20
21/* This is a NOEXEC applet. Be very careful! */
22
23int tac_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
24int tac_main(int argc, char **argv)
25{
26 char **name;
27 FILE *f;
28 char *line;
29 llist_t *list = NULL;
30 int retval = EXIT_SUCCESS;
Denis Vlasenko474d1c52008-01-07 19:06:47 +000031
Denis Vlasenko482f2b32008-01-07 16:14:14 +000032 argv++;
33 if (!*argv)
34 *--argv = (char *)"-";
35 /* We will read from last file to first */
36 name = argv;
37 while (*name)
38 name++;
39
40 do {
41 name--;
42 f = fopen_or_warn_stdin(*name);
43 if (f == NULL) {
44 retval = EXIT_FAILURE;
45 continue;
46 }
47
48 errno = 0;
49 /* FIXME: NUL bytes are mishandled. */
50 while ((line = xmalloc_fgets(f)) != NULL)
Denis Vlasenko474d1c52008-01-07 19:06:47 +000051 llist_add_to(&list, line);
Denis Vlasenko482f2b32008-01-07 16:14:14 +000052
53 /* xmalloc_fgets uses getc and returns NULL on error or EOF. */
54 /* It sets errno to ENOENT on EOF, but fopen_or_warn_stdin would */
55 /* catch this error so we can filter it out here. */
56 if (errno && errno != ENOENT) {
57 bb_simple_perror_msg(*name);
58 retval = EXIT_FAILURE;
59 }
60 } while (name != argv);
61
62 while (list) {
63 printf("%s", list->data);
64 list = list->link;
65 }
Denis Vlasenko474d1c52008-01-07 19:06:47 +000066
Denis Vlasenko482f2b32008-01-07 16:14:14 +000067 return retval;
68}