]> err.no Git - util-linux/commitdiff
rev: coding style, various fixes
authorDavidlohr Bueso <dave@gnu.org>
Sun, 8 Aug 2010 21:03:56 +0000 (17:03 -0400)
committerKarel Zak <kzak@redhat.com>
Fri, 20 Aug 2010 10:05:42 +0000 (12:05 +0200)
 * 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@gnu.org>
Signed-off-by: Karel Zak <kzak@redhat.com>
text-utils/rev.c

index 3ae38cfd6709cd8dd7e04fbe2f6b0051c5533018..907b032b1c95c6619308d44c2e00e7befe32ce72 100644 (file)
  * 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
+ *     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
+ *     added Native Language Support
  * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
- *     modified to work correctly in multi-byte locales
- *
+ *     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 <string.h>
 #include <unistd.h>
 #include <err.h>
+#include <signal.h>
 
 #include "nls.h"
 #include "widechar.h"
 
-void usage(void);
+wchar_t *buf;
 
-int
-main(int argc, char *argv[])
+static void sig_handler(int signo)
 {
-  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);
+       free(buf);
+       exit(EXIT_SUCCESS);
 }
 
-void
-usage(void)
+static void __attribute__((__noreturn__)) usage(FILE *out)
 {
-       (void)fprintf(stderr, _("usage: rev [file ...]\n"));
-       exit(1);
+       fprintf(out, _("Usage: %s [file ...]\n"),
+                       program_invocation_short_name);
+
+       fprintf(out, _("\nFor more information see rev(1).\n"));
+
+       exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
 }
+
+int main(int argc, char *argv[])
+{
+       char *filename = "stdin";
+       wchar_t *t;
+       size_t len, bufsiz = BUFSIZ;
+       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(_("%s: open failed"), *argv );
+                               rval = EXIT_FAILURE;
+                               ++argv;
+                               continue;
+                       }
+                       filename = *argv++;
+               }
+
+               buf = malloc(bufsiz * sizeof(wchar_t));
+               if (!buf)
+                       err(EXIT_FAILURE, _("malloc failed"));
+
+               while (fgetws(buf, bufsiz, fp)) {
+                       len = wcslen(buf);
+
+                       /* This is my hack from setpwnam.c -janl */
+                       while (buf[len-1] != '\n' && !feof(fp)) {
+                               wchar_t *x;
+
+                               /* Extend input buffer if it failed getting the whole line */
+
+                               /* So now we double the buffer size */
+                               bufsiz *= 2;
+
+                               x = realloc(buf, bufsiz * sizeof(wchar_t));
+                               if (!x) {
+                                       free(buf);
+                                       err(EXIT_FAILURE, _("realloc failed"));
+                               }
+                               buf = x;
+
+                               /* 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;
+}
+