rev: coding style, various 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@gnu.org> Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
1fc0b941d6
commit
06eee0d84f
195
text-utils/rev.c
195
text-utils/rev.c
|
@ -36,12 +36,16 @@
|
||||||
* Wed Sep 14 22:26:00 1994: Patch from bjdouma <bjdouma@xs4all.nl> to handle
|
* Wed Sep 14 22:26:00 1994: Patch from bjdouma <bjdouma@xs4all.nl> to handle
|
||||||
* last line that has no newline correctly.
|
* last line that has no newline correctly.
|
||||||
* 3-Jun-1998: Patched by Nicolai Langfeldt to work better on Linux:
|
* 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>
|
* 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>
|
* 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 <stdarg.h>
|
||||||
|
@ -52,94 +56,115 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include "nls.h"
|
#include "nls.h"
|
||||||
#include "widechar.h"
|
#include "widechar.h"
|
||||||
|
|
||||||
void usage(void);
|
wchar_t *buf;
|
||||||
|
|
||||||
int
|
static void sig_handler(int signo)
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
{
|
||||||
register char *filename;
|
free(buf);
|
||||||
register wchar_t *t;
|
exit(EXIT_SUCCESS);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void __attribute__((__noreturn__)) usage(FILE *out)
|
||||||
usage(void)
|
|
||||||
{
|
{
|
||||||
(void)fprintf(stderr, _("usage: rev [file ...]\n"));
|
fprintf(out, _("Usage: %s [file ...]\n"),
|
||||||
exit(1);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue