Bump to version 1.22.1
[platform/upstream/busybox.git] / util-linux / rev.c
1 /*
2  * rev implementation for busybox
3  *
4  * Copyright (C) 2010 Marek Polacek <mmpolacek@gmail.com>
5  *
6  * Licensed under GPLv2, see file LICENSE in this source tree.
7  */
8
9 //applet:IF_REV(APPLET(rev, BB_DIR_BIN, BB_SUID_DROP))
10
11 //kbuild:lib-$(CONFIG_REV) += rev.o
12
13 //config:config REV
14 //config:       bool "rev"
15 //config:       default y
16 //config:       help
17 //config:         Reverse lines of a file or files.
18
19 //usage:#define rev_trivial_usage
20 //usage:        "[FILE]..."
21 //usage:#define rev_full_usage "\n\n"
22 //usage:        "Reverse lines of FILE"
23
24 #include "libbb.h"
25 #include "unicode.h"
26
27 #undef CHAR_T
28 #if ENABLE_UNICODE_SUPPORT
29 # define CHAR_T wchar_t
30 #else
31 # define CHAR_T char
32 #endif
33
34 /* In-place invert */
35 static void strrev(CHAR_T *s, int len)
36 {
37         int i;
38
39         if (len != 0) {
40                 len--;
41                 if (len != 0 && s[len] == '\n')
42                         len--;
43         }
44
45         for (i = 0; i < len; i++, len--) {
46                 CHAR_T c = s[i];
47                 s[i] = s[len];
48                 s[len] = c;
49         }
50 }
51
52 int rev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
53 int rev_main(int argc UNUSED_PARAM, char **argv)
54 {
55         int retval;
56         size_t bufsize;
57         char *buf;
58
59         init_unicode();
60
61         getopt32(argv, "");
62         argv += optind;
63         if (!argv[0])
64                 argv = (char **)&bb_argv_dash;
65
66         retval = EXIT_SUCCESS;
67         bufsize = 256;
68         buf = xmalloc(bufsize);
69         do {
70                 size_t pos;
71                 FILE *fp;
72
73                 fp = fopen_or_warn_stdin(*argv++);
74                 if (!fp) {
75                         retval = EXIT_FAILURE;
76                         continue;
77                 }
78
79                 pos = 0;
80                 while (1) {
81                         /* Read one line */
82                         buf[bufsize - 1] = 1; /* not 0 */
83                         if (!fgets(buf + pos, bufsize - pos, fp))
84                                 break; /* EOF/error */
85                         if (buf[bufsize - 1] == '\0' /* fgets filled entire buffer */
86                          && buf[bufsize - 2] != '\n' /* and did not read '\n' */
87                          && !feof(fp)
88                         ) {
89                                 /* Line is too long, extend buffer */
90                                 pos = bufsize - 1;
91                                 bufsize += 64 + bufsize / 8;
92                                 buf = xrealloc(buf, bufsize);
93                                 continue;
94                         }
95
96                         /* Process and print it */
97 #if ENABLE_UNICODE_SUPPORT
98                         {
99                                 wchar_t *tmp = xmalloc(bufsize * sizeof(wchar_t));
100                                 /* Convert to wchar_t (might error out!) */
101                                 int len  = mbstowcs(tmp, buf, bufsize);
102                                 if (len >= 0) {
103                                         strrev(tmp, len);
104                                         /* Convert back to char */
105                                         wcstombs(buf, tmp, bufsize);
106                                 }
107                                 free(tmp);
108                         }
109 #else
110                         strrev(buf, strlen(buf));
111 #endif
112                         fputs(buf, stdout);
113                 }
114                 fclose(fp);
115         } while (*argv);
116
117         if (ENABLE_FEATURE_CLEAN_UP)
118                 free(buf);
119
120         fflush_stdout_and_exit(retval);
121 }