Hi Karel, >From our earlier discussion, I am resubmitting the rev patch with your suggested changes. Thanks, Davidlohr >From e9e0de2ef7b3ff66c133d9993ea2c6979bc612f8 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso <dave@xxxxxxx> Date: Sat, 7 Aug 2010 20:19:04 -0400 Subject: [PATCH] Revisions of rev(1) produces the following fixes: * Change indentation to 8 characters and coding style, for better reading the code. * Add some memory allocation error handling. * Fix memory leaks. In cases when Ctrl-C is used to exit the program, 'p' cannot be freed, so made it a global var, to share between main() and sig_handler(). Signal handing is necessary to fix some leaks, so added a very basic, non invasive, mechanism. Signed-off-by: Davidlohr Bueso <dave@xxxxxxx> --- text-utils/rev.c | 186 ++++++++++++++++++++++++++++++------------------------ 1 files changed, 104 insertions(+), 82 deletions(-) diff --git a/text-utils/rev.c b/text-utils/rev.c index 3ae38cf..19e1c61 100644 --- a/text-utils/rev.c +++ b/text-utils/rev.c @@ -41,7 +41,11 @@ * added Native Language Support * 1999-09-19 Bruno Haible <haible@xxxxxxxxxxxxxx> * modified to work correctly in multi-byte locales - * + * July 2010 - Davidlohr Bueso <dave@xxxxxxx> + * 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> @@ -52,94 +56,112 @@ #include <string.h> #include <unistd.h> #include <err.h> +#include <signal.h> #include "nls.h" #include "widechar.h" -void usage(void); +/* if not global, we cannot free it when SIGINTs occur */ +wchar_t *buf; + +static void sig_handler(int signo) +{ + switch(signo) { + case SIGINT: /* very used Ctrl-C when no file is passed as argv */ + case SIGTERM: + free(buf); + } + + exit(EXIT_SUCCESS); +} -int -main(int argc, char *argv[]) +static void usage(FILE *out) { - register char *filename; - register wchar_t *t; - size_t buflen = 512; - wchar_t *p = malloc(buflen*sizeof(wchar_t)); - size_t len; - FILE *fp; - int ch, rval; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - while ((ch = getopt(argc, argv, "")) != -1) - switch(ch) { - case '?': - default: - usage(); - } - - argc -= optind; - argv += optind; - - fp = stdin; - filename = "stdin"; - rval = 0; - do { - if (*argv) { - if ((fp = fopen(*argv, "r")) == NULL) { - warn("cannot open %s", *argv ); - rval = 1; - ++argv; - continue; - } - filename = *argv++; - } - - while (fgetws(p, buflen, fp)) { - - len = wcslen(p); - - /* This is my hack from setpwnam.c -janl */ - while (p[len-1] != '\n' && !feof(fp)) { - /* Extend input buffer if it failed getting the whole line */ - - /* So now we double the buffer size */ - buflen *= 2; - - p = realloc(p, buflen*sizeof(wchar_t)); - if (p == NULL) - err(1, _("unable to allocate bufferspace")); - - /* And fill the rest of the buffer */ - if (fgetws(&p[len], buflen/2, fp) == NULL) break; - - len = wcslen(p); - - /* That was a lot of work for nothing. Gimme perl! */ - } - - t = p + len - 1 - (*(p+len-1)=='\r' || *(p+len-1)=='\n'); - for ( ; t >= p; --t) - if (*t != 0) - putwchar(*t); - putwchar('\n'); - } - fflush(fp); - if (ferror(fp)) { - warn("%s", filename); - rval = 1; - } - if (fclose(fp)) - rval = 1; - } while(*argv); - exit(rval); + fprintf(stderr, _("usage: rev [file ...]\n")); + + exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } -void -usage(void) +int main(int argc, char *argv[]) { - (void)fprintf(stderr, _("usage: rev [file ...]\n")); - exit(1); + char *filename = "stdin"; + wchar_t *t; + size_t len, bufsiz = 256; + FILE *fp = stdin; + int ch, rval = EXIT_SUCCESS; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + + while ((ch = getopt(argc, argv, "")) != -1) + switch(ch) { + case '?': + case 'h': + usage(stdout); + default: + usage(stderr); + } + + argc -= optind; + argv += optind; + + do { + if (*argv) { + if ((fp = fopen(*argv, "r")) == NULL) { + warn("cannot open %s", *argv ); + rval = EXIT_FAILURE; + ++argv; + continue; + } + filename = *argv++; + } + + buf = malloc(bufsiz * sizeof(wchar_t)); + if (!buf) + err(EXIT_FAILURE, _("unable to allocate bufferspace")); + + while (fgetws(buf, bufsiz, fp)) { + len = wcslen(buf); + + /* 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 = realloc(buf, bufsiz * sizeof(wchar_t)); + if (!buf) { + free(buf); + err(EXIT_FAILURE, _("unable to allocate bufferspace")); + } + /* And fill the rest of the buffer */ + if (!fgetws(&buf[len], bufsiz/2, fp)) + break; + + len = wcslen(buf); + } + + t = buf + len - 1 - (*(buf+len-1)=='\r' || *(buf+len-1)=='\n'); + for ( ; t >= buf; --t) + if (*t != 0) + putwchar(*t); + putwchar('\n'); + } + + fflush(fp); + if (ferror(fp)) { + warn("%s", filename); + rval = EXIT_FAILURE; + } + if (fclose(fp)) + rval = EXIT_FAILURE; + } while(*argv); + + free(buf); + return rval; } -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html