use short options when getopt.h isn't present

This commit is contained in:
Ron Pedde 2005-02-28 21:49:51 +00:00
parent f4e8bc9625
commit f3b6ef46f9

View File

@ -23,22 +23,29 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h> #include <getopt.h>
#endif
char *av0; char *av0;
struct option longopts[] = struct option longopts[] =
{ { "help", 0, NULL, 'h' }, { { "help", 0, NULL, 'h' },
{ "samples", 1, NULL, 's' }, { "samples", 1, NULL, 's' },
{ "length", 1, NULL, 'l' }, { "length", 1, NULL, 'l' },
{ "offset", 1, NULL, '0' }, { "offset", 1, NULL, '0' },
{ NULL, 0, NULL, 0 } }; { NULL, 0, NULL, 0 } };
#define GET_WAV_INT32(p) ((((unsigned long)((p)[3])) << 24) | \ #define GET_WAV_INT32(p) ((((unsigned long)((p)[3])) << 24) | \
(((unsigned long)((p)[2])) << 16) | \ (((unsigned long)((p)[2])) << 16) | \
@ -50,38 +57,38 @@ struct option longopts[] =
unsigned char *read_hdr(FILE *f, size_t *hdr_len) unsigned char *read_hdr(FILE *f, size_t *hdr_len)
{ {
unsigned char *hdr; unsigned char *hdr;
unsigned long format_data_length; unsigned long format_data_length;
hdr = malloc(256); hdr = malloc(256);
if (hdr == NULL) if (hdr == NULL)
return NULL; return NULL;
if (fread(hdr, 44, 1, f) != 1) if (fread(hdr, 44, 1, f) != 1)
goto fail; goto fail;
if (strncmp(hdr + 12, "fmt ", 4)) if (strncmp(hdr + 12, "fmt ", 4))
goto fail; goto fail;
format_data_length = GET_WAV_INT32(hdr + 16); format_data_length = GET_WAV_INT32(hdr + 16);
if ((format_data_length < 16) || (format_data_length > 100)) if ((format_data_length < 16) || (format_data_length > 100))
goto fail; goto fail;
*hdr_len = 44; *hdr_len = 44;
if (format_data_length > 16) { if (format_data_length > 16) {
if (fread(hdr + 44, format_data_length - 16, 1, f) != 1) if (fread(hdr + 44, format_data_length - 16, 1, f) != 1)
goto fail; goto fail;
*hdr_len += format_data_length - 16; *hdr_len += format_data_length - 16;
} }
return hdr; return hdr;
fail: fail:
if (hdr != NULL) if (hdr != NULL)
free(hdr); free(hdr);
return NULL; return NULL;
} }
size_t parse_hdr(unsigned char *hdr, size_t hdr_len, size_t parse_hdr(unsigned char *hdr, size_t hdr_len,
@ -93,48 +100,48 @@ size_t parse_hdr(unsigned char *hdr, size_t hdr_len,
unsigned long *sample_bit_length_ret, unsigned long *sample_bit_length_ret,
unsigned long *data_length_ret) unsigned long *data_length_ret)
{ {
unsigned long chunk_data_length; unsigned long chunk_data_length;
unsigned long format_data_length; unsigned long format_data_length;
unsigned long compression_code; unsigned long compression_code;
unsigned long channel_count; unsigned long channel_count;
unsigned long sample_rate; unsigned long sample_rate;
unsigned long sample_bit_length; unsigned long sample_bit_length;
unsigned long data_length; unsigned long data_length;
if (strncmp(hdr + 0, "RIFF", 4) || if (strncmp(hdr + 0, "RIFF", 4) ||
strncmp(hdr + 8, "WAVE", 4) || strncmp(hdr + 8, "WAVE", 4) ||
strncmp(hdr + 12, "fmt ", 4)) strncmp(hdr + 12, "fmt ", 4))
return 0; return 0;
format_data_length = GET_WAV_INT32(hdr + 16); format_data_length = GET_WAV_INT32(hdr + 16);
if (strncmp(hdr + 20 + format_data_length, "data", 4)) if (strncmp(hdr + 20 + format_data_length, "data", 4))
return 0; return 0;
chunk_data_length = GET_WAV_INT32(hdr + 4); chunk_data_length = GET_WAV_INT32(hdr + 4);
compression_code = GET_WAV_INT16(hdr + 20); compression_code = GET_WAV_INT16(hdr + 20);
channel_count = GET_WAV_INT16(hdr + 22); channel_count = GET_WAV_INT16(hdr + 22);
sample_rate = GET_WAV_INT32(hdr + 24); sample_rate = GET_WAV_INT32(hdr + 24);
sample_bit_length = GET_WAV_INT16(hdr + 34); sample_bit_length = GET_WAV_INT16(hdr + 34);
data_length = GET_WAV_INT32(hdr + 20 + format_data_length + 4); data_length = GET_WAV_INT32(hdr + 20 + format_data_length + 4);
if ((format_data_length != 16) || if ((format_data_length != 16) ||
(compression_code != 1) || (compression_code != 1) ||
(channel_count < 1) || (channel_count < 1) ||
(sample_rate == 0) || (sample_rate == 0) ||
(sample_rate > 512000) || (sample_rate > 512000) ||
(sample_bit_length < 2)) (sample_bit_length < 2))
return 0; return 0;
*chunk_data_length_ret = chunk_data_length; *chunk_data_length_ret = chunk_data_length;
*format_data_length_ret = format_data_length; *format_data_length_ret = format_data_length;
*compression_code_ret = compression_code; *compression_code_ret = compression_code;
*channel_count_ret = channel_count; *channel_count_ret = channel_count;
*sample_rate_ret = sample_rate; *sample_rate_ret = sample_rate;
*sample_bit_length_ret = sample_bit_length; *sample_bit_length_ret = sample_bit_length;
*data_length_ret = data_length; *data_length_ret = data_length;
return 20 + format_data_length + 8; return 20 + format_data_length + 8;
} }
size_t patch_hdr(unsigned char *hdr, size_t hdr_len, size_t patch_hdr(unsigned char *hdr, size_t hdr_len,
@ -142,256 +149,266 @@ size_t patch_hdr(unsigned char *hdr, size_t hdr_len,
unsigned long samples, unsigned long samples,
size_t *data_length_ret) size_t *data_length_ret)
{ {
unsigned long chunk_data_length; unsigned long chunk_data_length;
unsigned long format_data_length; unsigned long format_data_length;
unsigned long compression_code; unsigned long compression_code;
unsigned long channel_count; unsigned long channel_count;
unsigned long sample_rate; unsigned long sample_rate;
unsigned long sample_bit_length; unsigned long sample_bit_length;
unsigned long data_length; unsigned long data_length;
unsigned long bytes_per_sample; unsigned long bytes_per_sample;
if (parse_hdr(hdr, hdr_len, if (parse_hdr(hdr, hdr_len,
&chunk_data_length, &chunk_data_length,
&format_data_length, &format_data_length,
&compression_code, &compression_code,
&channel_count, &channel_count,
&sample_rate, &sample_rate,
&sample_bit_length, &sample_bit_length,
&data_length) != hdr_len) &data_length) != hdr_len)
return 0; return 0;
if (hdr_len != (20 + format_data_length + 8)) if (hdr_len != (20 + format_data_length + 8))
return 0; return 0;
if (format_data_length > 16) { if (format_data_length > 16) {
memmove(hdr + 20 + 16, hdr + 20 + format_data_length, 8); memmove(hdr + 20 + 16, hdr + 20 + format_data_length, 8);
hdr[16] = 16; hdr[16] = 16;
hdr[17] = 0; hdr[17] = 0;
hdr[18] = 0; hdr[18] = 0;
hdr[19] = 0; hdr[19] = 0;
format_data_length = 16; format_data_length = 16;
hdr_len = 44; hdr_len = 44;
}
bytes_per_sample = channel_count * ((sample_bit_length + 7) / 8);
if (samples == 0)
{
samples = sample_rate * sec;
samples += ((sample_rate / 100) * (us / 10)) / 1000;
} }
if (samples > 0) { bytes_per_sample = channel_count * ((sample_bit_length + 7) / 8);
data_length = samples * bytes_per_sample;
chunk_data_length = data_length + 36;
} else {
chunk_data_length = 0xffffffff;
data_length = chunk_data_length - 36;
}
if (data_length_ret != NULL) if (samples == 0) {
*data_length_ret = data_length; samples = sample_rate * sec;
samples += ((sample_rate / 100) * (us / 10)) / 1000;
}
hdr[4] = chunk_data_length % 0x100; if (samples > 0) {
hdr[5] = (chunk_data_length >> 8) % 0x100; data_length = samples * bytes_per_sample;
hdr[6] = (chunk_data_length >> 16) % 0x100; chunk_data_length = data_length + 36;
hdr[7] = (chunk_data_length >> 24) % 0x100; } else {
chunk_data_length = 0xffffffff;
data_length = chunk_data_length - 36;
}
hdr[40] = data_length % 0x100; if (data_length_ret != NULL)
hdr[41] = (data_length >> 8) % 0x100; *data_length_ret = data_length;
hdr[42] = (data_length >> 16) % 0x100;
hdr[43] = (data_length >> 24) % 0x100;
return hdr_len; hdr[4] = chunk_data_length % 0x100;
hdr[5] = (chunk_data_length >> 8) % 0x100;
hdr[6] = (chunk_data_length >> 16) % 0x100;
hdr[7] = (chunk_data_length >> 24) % 0x100;
hdr[40] = data_length % 0x100;
hdr[41] = (data_length >> 8) % 0x100;
hdr[42] = (data_length >> 16) % 0x100;
hdr[43] = (data_length >> 24) % 0x100;
return hdr_len;
} }
static void usage(int exitval); static void usage(int exitval);
static void usage(int exitval) static void usage(int exitval)
{ {
fprintf(stderr, fprintf(stderr,
"Usage: %s [ options ] [input-file]\n", av0); "Usage: %s [ options ] [input-file]\n", av0);
fprintf(stderr, fprintf(stderr,
"\n"); "\n");
fprintf(stderr, fprintf(stderr,
"Options:\n"); "Options:\n");
fprintf(stderr, fprintf(stderr,
"-l len | --length=len Length of the sound file in seconds.\n"); "-l len | --length=len Length of the sound file in seconds.\n");
fprintf(stderr, fprintf(stderr,
"-s len | --samples=len Length of the sound file in samples.\n"); "-s len | --samples=len Length of the sound file in samples.\n");
fprintf(stderr, fprintf(stderr,
"-o offset | --offset=offset Number of bytes to discard from the stream.\n"); "-o offset | --offset=offset Number of bytes to discard from the stream.\n");
fprintf(stderr, fprintf(stderr,
"\n"); "\n");
fprintf(stderr, fprintf(stderr,
"--samples and --length are mutually exclusive.\n"); "--samples and --length are mutually exclusive.\n");
exit(exitval); #ifndef HAVE_GETOPT_H
fprintf(stderr,
"\n\nLong options are not availabl eon this system.\n");
#endif
exit(exitval);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int c; int c;
unsigned long sec = 0, us = 0, samples = 0; unsigned long sec = 0, us = 0, samples = 0;
unsigned long offset = 0; unsigned long offset = 0;
unsigned long skip = 0; unsigned long skip = 0;
char *end; char *end;
FILE *f; FILE *f;
unsigned char *hdr; unsigned char *hdr;
size_t hdr_len; size_t hdr_len;
size_t data_len; size_t data_len;
unsigned char buf[0x1000]; unsigned char buf[0x1000];
size_t buf_len; size_t buf_len;
if (strchr(argv[0], '/')) if (strchr(argv[0], '/'))
av0 = strrchr(argv[0], '/') + 1; av0 = strrchr(argv[0], '/') + 1;
else else
av0 = argv[0]; av0 = argv[0];
while ((c = getopt_long(argc, argv, "+hl:o:s:", longopts, NULL)) != EOF) #ifdef HAVE_GETOPT_H
switch(c) while ((c = getopt_long(argc, argv, "+hl:o:s:", longopts, NULL)) != EOF) {
{ #else
case 'h': while ((c = getopt(argc, argv, "hl:o:s:")) != -1) {
usage(0); #endif
/*NOTREACHED*/ switch(c) {
break; case 'h':
usage(0);
case 'l': /*NOTREACHED*/
sec = strtoul(optarg, &end, 10); break;
if ((*optarg == '-') || (end == optarg) || ((*end != '\0') && (*end != '.'))) {
fprintf(stderr, "%s: Invalid -l argument.\n", av0); case 'l':
exit(-1); sec = strtoul(optarg, &end, 10);
} else if (*end == '.') { if ((*optarg == '-') || (end == optarg) || ((*end != '\0') && (*end != '.'))) {
char tmp[7]; fprintf(stderr, "%s: Invalid -l argument.\n", av0);
int i; exit(-1);
} else if (*end == '.') {
char tmp[7];
int i;
memset(tmp, '0', sizeof (tmp) - 1);
tmp[sizeof (tmp) - 1] = '\0';
for (i = 0; (i < (sizeof (tmp) - 1)) && (isdigit(end[i+1])); i++)
tmp[i] = end[i+1];
us = strtoul(tmp, NULL, 10);
} else {
us = 0;
}
memset(tmp, '0', sizeof (tmp) - 1); if ((sec == 0) && (us == 0)) {
tmp[sizeof (tmp) - 1] = '\0'; fprintf(stderr, "%s: Invalid -l argument (zero is not acceptable).\n", av0);
for (i = 0; (i < (sizeof (tmp) - 1)) && (isdigit(end[i+1])); i++) exit(-1);
tmp[i] = end[i+1]; }
us = strtoul(tmp, NULL, 10);
} else {
us = 0;
}
if ((sec == 0) && (us == 0)) {
fprintf(stderr, "%s: Invalid -l argument (zero is not acceptable).\n", av0);
exit(-1);
}
if (samples != 0) {
fprintf(stderr, "%s: Parameters -s and -l are mutually exclusive.\n", av0);
exit(-1);
}
break;
case 's': if (samples != 0) {
samples = strtoul(optarg, &end, 10); fprintf(stderr, "%s: Parameters -s and -l are mutually exclusive.\n", av0);
if ((*optarg == '-') || (end == optarg) || (*end != '\0')) { exit(-1);
fprintf(stderr, "%s: Invalid -s argument.\n", av0); }
exit(-1); break;
case 's':
samples = strtoul(optarg, &end, 10);
if ((*optarg == '-') || (end == optarg) || (*end != '\0')) {
fprintf(stderr, "%s: Invalid -s argument.\n", av0);
exit(-1);
}
if (samples == 0) {
fprintf(stderr, "%s: Invalid -s argument (zero is not acceptable).\n", av0);
exit(-1);
}
if ((sec != 0) || (us != 0)) {
fprintf(stderr, "%s: Parameters -l and -s are mutually exclusive.\n", av0);
exit(-1);
}
break;
case 'o':
offset = strtoul(optarg, &end, 10);
if ((*optarg == '-') || (end == optarg) || (*end != '\0')) {
fprintf(stderr, "%s: Invalid -o argument.\n", av0);
exit(-1);
}
break;
default:
fprintf(stderr, "%s: Bad command line option -%c.\n", av0, optopt);
usage(-1);
}
}
argc -= optind;
argv += optind;
if (argc == 0) {
f = stdin;
} else if (argc == 1) {
f = fopen(argv[0], "rb");
if (f == NULL) {
fprintf(stderr, "%s: Can't open file %s for reading.\n", av0, argv[0]);
exit(1);
}
} else {
fprintf(stderr, "%s: Too many command line arguments.\n", av0);
usage(-1);
}
hdr = read_hdr(f, &hdr_len);
if (hdr == NULL) {
fprintf(stderr, "%s: Can't read wav header.\n", av0);
exit(2);
}
if ((hdr_len = patch_hdr(hdr, hdr_len, sec, us, samples, &data_len)) == 0) {
free(hdr);
fprintf(stderr, "%s: Can't parse (or patch) wav header.\n", av0);
exit(2);
}
if (offset > hdr_len + data_len) {
fprintf(stderr, "%s: Offset is beyond EOF.\n", av0);
exit(3);
}
if ((offset > 0) && (offset < hdr_len)) {
memmove(hdr, hdr + offset, hdr_len - offset);
hdr_len -= offset;
offset = 0;
}
if (offset > 0) {
offset -= hdr_len;
} else {
if (fwrite(hdr, hdr_len, 1, stdout) != 1) {
fprintf(stderr, "%s: Write failed.\n", av0);
exit(4);
} }
if (samples == 0) {
fprintf(stderr, "%s: Invalid -s argument (zero is not acceptable).\n", av0);
exit(-1);
}
if ((sec != 0) || (us != 0)) {
fprintf(stderr, "%s: Parameters -l and -s are mutually exclusive.\n", av0);
exit(-1);
}
break;
case 'o':
offset = strtoul(optarg, &end, 10);
if ((*optarg == '-') || (end == optarg) || (*end != '\0')) {
fprintf(stderr, "%s: Invalid -o argument.\n", av0);
exit(-1);
}
break;
default:
fprintf(stderr, "%s: Bad command line option -%c.\n", av0, optopt);
usage(-1);
}
argc -= optind;
argv += optind;
if (argc == 0) {
f = stdin;
} else if (argc == 1) {
f = fopen(argv[0], "rb");
if (f == NULL) {
fprintf(stderr, "%s: Can't open file %s for reading.\n", av0, argv[0]);
exit(1);
} }
} else {
fprintf(stderr, "%s: Too many command line arguments.\n", av0);
usage(-1);
}
hdr = read_hdr(f, &hdr_len);
if (hdr == NULL) {
fprintf(stderr, "%s: Can't read wav header.\n", av0);
exit(2);
}
if ((hdr_len = patch_hdr(hdr, hdr_len, sec, us, samples, &data_len)) == 0) {
free(hdr); free(hdr);
fprintf(stderr, "%s: Can't parse (or patch) wav header.\n", av0); hdr = NULL;
exit(2); hdr_len = 0;
}
if (offset > hdr_len + data_len) { if (offset > 0) {
fprintf(stderr, "%s: Offset is beyond EOF.\n", av0); data_len -= offset;
exit(3); while (offset > 0) {
} buf_len = (offset > sizeof (buf)) ? sizeof (buf) : offset;
if (fread(buf, buf_len, 1, f) != 1) {
if ((offset > 0) && (offset < hdr_len)) { fprintf(stderr, "%s: Read failed.\n", av0);
memmove(hdr, hdr + offset, hdr_len - offset); exit(5);
hdr_len -= offset; }
offset = 0; offset -= buf_len;
} }
if (offset > 0) {
offset -= hdr_len;
} else {
if (fwrite(hdr, hdr_len, 1, stdout) != 1) {
fprintf(stderr, "%s: Write failed.\n", av0);
exit(4);
} }
}
free(hdr); while (data_len > 0) {
hdr = NULL; buf_len = (data_len > sizeof (buf)) ? sizeof (buf) : data_len;
hdr_len = 0; if (fread(buf, buf_len, 1, f) != 1) {
fprintf(stderr, "%s: Read failed.\n", av0);
if (offset > 0) { exit(5);
data_len -= offset; }
while (offset > 0) { if (fwrite(buf, buf_len, 1, stdout) != 1) {
buf_len = (offset > sizeof (buf)) ? sizeof (buf) : offset; fprintf(stderr, "%s: Write failed.\n", av0);
if (fread(buf, buf_len, 1, f) != 1) { exit(4);
fprintf(stderr, "%s: Read failed.\n", av0); }
exit(5); data_len -= buf_len;
}
offset -= buf_len;
} }
}
while (data_len > 0) { if (f != stdout) {
buf_len = (data_len > sizeof (buf)) ? sizeof (buf) : data_len; fclose(f);
if (fread(buf, buf_len, 1, f) != 1) {
fprintf(stderr, "%s: Read failed.\n", av0);
exit(5);
} }
if (fwrite(buf, buf_len, 1, stdout) != 1) { exit(0);
fprintf(stderr, "%s: Write failed.\n", av0);
exit(4);
}
data_len -= buf_len;
}
if (f != stdout) {
fclose(f);
}
exit(0);
} }