diff options
Diffstat (limited to 'text-utils/rev.c')
-rw-r--r-- | text-utils/rev.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/text-utils/rev.c b/text-utils/rev.c new file mode 100644 index 0000000..13a41f6 --- /dev/null +++ b/text-utils/rev.c @@ -0,0 +1,183 @@ +/*- + * Copyright (c) 1987, 1992 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Modified for Linux by Charles Hannum (mycroft@gnu.ai.mit.edu) + * and Brian Koehmstedt (bpk@gnu.ai.mit.edu) + * + * Wed Sep 14 22:26:00 1994: Patch from bjdouma <bjdouma@xs4all.nl> to handle + * last line that has no newline correctly. + * 3-Jun-1998: Patched by Nicolai Langfeldt to work better on Linux: + * Handle any-length-lines. Code copied from util-linux' setpwnam.c + * 1999-02-22 Arkadiusz MiĆkiewicz <misiek@pld.ORG.PL> + * added Native Language Support + * 1999-09-19 Bruno Haible <haible@clisp.cons.org> + * modified to work correctly in multi-byte locales + * July 2010 - Davidlohr Bueso <dave@gnu.org> + * Fixed memory leaks (including Linux signal handling) + * Added some memory allocation error handling + * Lowered the default buffer size to 256, instead of 512 bytes + * Changed tab indentation to 8 chars for better reading the code + */ + +#include <stdarg.h> +#include <sys/types.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> +#include <getopt.h> + +#include "nls.h" +#include "xalloc.h" +#include "widechar.h" +#include "c.h" +#include "closestream.h" + +static void sig_handler(int signo __attribute__ ((__unused__))) +{ + _exit(EXIT_SUCCESS); +} + +static void __attribute__((__noreturn__)) usage(void) +{ + FILE *out = stdout; + fprintf(out, _("Usage: %s [options] [file ...]\n"), + program_invocation_short_name); + + fputs(USAGE_SEPARATOR, out); + fputs(_("Reverse lines characterwise.\n"), out); + + fputs(USAGE_OPTIONS, out); + printf(USAGE_HELP_OPTIONS(16)); + printf(USAGE_MAN_TAIL("rev(1)")); + + exit(EXIT_SUCCESS); +} + +static void reverse_str(wchar_t *str, size_t n) +{ + size_t i; + + for (i = 0; i < n / 2; ++i) { + wchar_t tmp = str[i]; + str[i] = str[n - 1 - i]; + str[n - 1 - i] = tmp; + } +} + +int main(int argc, char *argv[]) +{ + char const *filename = "stdin"; + wchar_t *buf; + size_t len, bufsiz = BUFSIZ; + FILE *fp = stdin; + int ch, rval = EXIT_SUCCESS; + + static const struct option longopts[] = { + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + { NULL, 0, NULL, 0 } + }; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + atexit(close_stdout); + + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + + while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1) + switch(ch) { + case 'V': + printf(UTIL_LINUX_VERSION); + exit(EXIT_SUCCESS); + case 'h': + usage(); + default: + errtryhelp(EXIT_FAILURE); + } + + argc -= optind; + argv += optind; + + buf = xmalloc(bufsiz * sizeof(wchar_t)); + + do { + if (*argv) { + if ((fp = fopen(*argv, "r")) == NULL) { + warn(_("cannot open %s"), *argv ); + rval = EXIT_FAILURE; + ++argv; + continue; + } + filename = *argv++; + } + + while (fgetws(buf, bufsiz, fp)) { + len = wcslen(buf); + + if (len == 0) + continue; + + /* This is my hack from setpwnam.c -janl */ + while (buf[len-1] != '\n' && !feof(fp)) { + /* Extend input buffer if it failed getting the whole line */ + /* So now we double the buffer size */ + bufsiz *= 2; + + buf = xrealloc(buf, bufsiz * sizeof(wchar_t)); + + /* And fill the rest of the buffer */ + if (!fgetws(&buf[len], bufsiz/2, fp)) + break; + + len = wcslen(buf); + } + if (buf[len - 1] == '\n') + buf[len--] = '\0'; + reverse_str(buf, len); + fputws(buf, stdout); + } + if (ferror(fp)) { + warn("%s", filename); + rval = EXIT_FAILURE; + } + fclose(fp); + } while(*argv); + + free(buf); + return rval; +} + |