diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-01-07 16:14:14 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-01-07 16:14:14 +0000 |
commit | 482f2b31e788fdd849f78a3aa91cf6102fc98892 (patch) | |
tree | e6c65061607ac152091ea4bbda98ae16494d0f2e /coreutils/tac.c | |
parent | 6b404431aa7adea24120894d59daeebc5cbe9727 (diff) | |
download | busybox-w32-482f2b31e788fdd849f78a3aa91cf6102fc98892.tar.gz busybox-w32-482f2b31e788fdd849f78a3aa91cf6102fc98892.tar.bz2 busybox-w32-482f2b31e788fdd849f78a3aa91cf6102fc98892.zip |
tac: *really* add tac.c now
Diffstat (limited to 'coreutils/tac.c')
-rw-r--r-- | coreutils/tac.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/coreutils/tac.c b/coreutils/tac.c new file mode 100644 index 000000000..6aa0528e0 --- /dev/null +++ b/coreutils/tac.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* 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 | |||
23 | int tac_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
24 | int 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; | ||
31 | |||
32 | 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) | ||
51 | llist_add_to(&list, line); | ||
52 | |||
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 | } | ||
66 | |||
67 | return retval; | ||
68 | } | ||