busybox/util-linux/rev.c
<<
>>
Prefs
   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 */
  35static 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
  52int rev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  53int 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}
 122