/**
* strip-null-bytes: A small C program which strips null bytes
* at beginning and end of STDIN and echos the data (without the
* null bytes) to STDOUT.
*
* why not a perl tool? perl is nice for complex jobs, but not for
* something like this low level thing ;-)
*
* (c) 14.06.08 Sven Köppel
*
**/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DPRINTF(bla...) { if(flag_debug) fprintf(stderr,bla); }
int stream_get_contents(FILE *stream, unsigned char **content) {
/**
* helper function to read in stdin into heap array; from
* PaperTape cairo project -> from Glib.
**/
unsigned char buf[4096];
size_t bytes; // gerade eben eingelesene bytes
unsigned char *str = NULL;
size_t total_bytes = 0; // alle bis jetzt eingelesenen bytes
size_t total_allocated = 0;
unsigned char *tmp; // fuers realloc
while(!feof(stream)) {
bytes = fread(buf, 1, sizeof(buf), stream);
while( (total_bytes + bytes) > total_allocated) {
if(str)
total_allocated *= 2;
else
total_allocated = bytes > sizeof(buf) ? bytes : sizeof(buf);
tmp = realloc(str, total_allocated);
if(tmp == NULL) {
fprintf(stderr, "*** file_get_contents ERROR *** Could not reallocate\n");
exit(1);
}
str = tmp;
} // while innen
memcpy(str + total_bytes, buf, bytes);
total_bytes += bytes;
} // while
if(total_allocated == 0)
str = malloc(1); // ein leerer String halt.
*content = str;
return total_bytes;
}
int main(int argc, char **argv) {
unsigned char *bytes;
int length;
int x_start, x_end, x;
int flag_start, flag_end, flag_debug;
flag_debug = flag_start = flag_end = 0;
int c;
while( (c = getopt(argc, argv, "bsehd")) != -1)
switch(c) {
case 'd':
flag_debug = 1;
break;
case 'h':
fprintf(stderr, "Usage: %s [-d] [-s/b] [-e] [-h]\n"
" optional parameters:\n"
" -d debug mode (print everything to stderr)\n"
" -h display this help message\n\n"
" -b same as -s\n"
" -s strip null bytes at START of stdin\n"
" -e strip null bytes a END of stdin\n\n"
" without any parameters, null bytes will be stripped\n"
" both at start and at end of stdin.\n"
,argv[0]);
return 0;
case 'b':
case 's':
flag_start = 1;
break;
case 'e':
flag_end = 1;
}
DPRINTF("Reading in from stdin, finish with eof/[STRG] + [D]\n");
length = stream_get_contents(stdin, &bytes);
DPRINTF("Finished reading in.\n");
/* stripping at start */
if( flag_start || (!flag_start && !flag_end) )
for(x_start = 0; x_start < length; x_start++) {
DPRINTF("start char %d/%d: 0x%x\n", x_start, length, bytes[x_start]);
if(bytes[x_start])
break;
}
else {
x_start = 0;
DPRINTF("skipping stripping at start\n");
}
/* stripping at end */
if( flag_end || (!flag_start && !flag_end) )
for(x_end = length; x_end > 0; x_end--) {
DPRINTF("end char %d/%d: 0x%x\n", x_end, length, bytes[x_end]);
if(bytes[x_end])
break;
}
else {
x_end = length;
DPRINTF("skipping stripping at end\n");
}
DPRINTF("found data chunk: begin at %d, end at %d\n", x_start, x_end);
for(x=x_start; x<=x_end; x++)
fputc(bytes[x], stdout);
return 0;
}