Hi,
this new version of tac.c handles embedded nulls in a correct way.
I tested it in comparison with the real tac on most of the files 
of my hard disk with the attached script and it seems to work.
Before posting a patch I would like the list members to take
a look at this new approach for hints, improvements and critics.
For the same reason I have not checked the size increase yet.

Ciao,
Tito

Attachment: tac_test.sh
Description: application/shellscript

/* vi: set sw=4 ts=4: */
/*
 * tac implementation for busybox
 *
 * Copyright (C) 2003  Yang Xiaopeng  <yxp at hanwang.com.cn>
 * Copyright (C) 2007  Natanael Copa  <[EMAIL PROTECTED]>
 * Copyright (C) 2007  Tito Ragusa    <[EMAIL PROTECTED]>
 *
 * Licensed under GPLv2, see file License in this tarball for details.
 *
 */

/* tac - concatenate and print files in reverse */

/* Based on Yang Xiaopeng's (yxp at hanwang.com.cn) patch
 * http://www.uclibc.org/lists/busybox/2003-July/008813.html
 */

#include "libbb.h"

/* This is a NOEXEC applet. Be very careful! */

int tac_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int tac_main(int argc, char **argv)
{
	char **name;
	FILE *f;
	char *line = NULL;
	llist_t *list = NULL;
	int retval = EXIT_SUCCESS;
	int i;
	int ch;
	int *size = NULL;

	argv++;
	if (!*argv)
		*--argv = (char *)"-";
	/* We will read from last file to first */
	name = argv;
	while (*name)
		name++;

	do {
		name--;
		f = fopen_or_warn_stdin(*name);
		if (f == NULL) {
			retval = EXIT_FAILURE;
			continue;
		}

		i = errno = 0;

		while (1) {
			ch = fgetc(f);
			line = xrealloc(line, i + 1);
			if (ch == EOF)
				goto line_end;
			line[i] = ch;
			i++;
			if (ch == '\n' || ch == EOF) {
 line_end:
				/* Save the size of the line to the list */
				size = xmalloc(sizeof(int *));
				llist_add_to(&list, memcpy(size, &i, sizeof(int)));
				llist_add_to(&list, line);
				line = NULL;
				i = 0;
			}
			if (ch == EOF)
				break;
		}
		/* fgetc sets errno to ENOENT on EOF, but     */
		/* fopen_or_warn_stdin would catch this error */
		/* so we can filter it out here.              */
		if (errno && errno != ENOENT) {
			bb_simple_perror_msg(*name);
			retval = EXIT_FAILURE;
		}
	} while (name != argv);

	while (list) {
		line = llist_pop(&list);
		size = llist_pop(&list);
		full_write(STDOUT_FILENO, line, *size);
		if (ENABLE_FEATURE_CLEAN_UP) {
			free(line);
			free(size);
		}
	}

	return retval;
}
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to