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