123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- #include <assert.h>
- #include <errno.h>
- #include <inttypes.h>
- #include <limits.h>
- #include <signal.h>
- #include <stddef.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <fcntl.h>
- #include <poll.h>
- #include <unistd.h>
- #ifdef USE_CAPSICUM
- #include <sys/capsicum.h>
- #endif
- #include <err.h>
- #include <sysexits.h>
- #include "au.h"
- #include "write/afile.h"
- #include "common.h"
- #ifndef NAMEMAX
- #define NAMEMAX 10
- #endif
- #ifndef BSIZE
- #define BSIZE 0x1000
- #endif
- #ifdef SIGINFO
- #define IFINFO(x) (x)
- #else
- #define IFINFO(x)
- #endif
- static sigset_t sigpend;
- #ifdef SIGINFO
- static size_t info_bytes = 0;
- #endif
- static void sighandle(int);
- #ifdef SIGINFO
- static void siginfo(int);
- #endif
- int
- main(int argc, char *argv[])
- {
- #ifdef USE_CAPSICUM
- cap_rights_t rights;
- #endif
- #ifdef USE_BITRATE
- uint32_t bitrate = 0;
- #endif
- #ifdef USE_MODE
- char *amode = NULL;
- #endif
- #ifdef USE_QUALITY
- double quality = 1;
- #endif
- int cpipe[2];
- pid_t cpid = 0;
- uint32_t enc;
- struct au au = AU_INITIALIZER;
- struct afile *a;
- ssize_t i;
- ssize_t r;
- size_t bsize = BSIZE;
- void *b;
- char *p;
- int c;
- setprogname(argv[0]);
- while ((c = getopt(argc, argv, "B:C:I:RWb:c:i:m:q:")) != -1)
- switch (c) {
- case 'B':
- #ifdef USE_BITRATE
- bitrate = strtou32(optarg);
- #endif
- break;
- case 'b':
- bsize = strtoul(optarg, &p, 0);
- if (p == optarg || *p != '\0')
- errx(EX_USAGE, "Invalid number '%s'",
- optarg);
- if (bsize < 0x400)
- errx(EX_USAGE, "The buffer size (%zu) "
- "is too small", bsize);
- break;
- case 'm':
- #ifdef USE_MODE
- amode = optarg;
- #endif
- break;
- case 'q':
- #ifdef USE_QUALITY
- quality = strtod(optarg, &p);
- if (p == optarg || *p != '\0')
- errx(EX_USAGE, "Invalid number '%s'",
- optarg);
- #endif
- break;
- default:
- goto usage;
- }
- if ((b = malloc(bsize)) == NULL)
- err(EX_OSERR, "Could not allocate the buffer");
- sigemptyset(&sigpend);
- (void)signal(SIGINT, &sighandle);
- IFINFO((void)signal(SIGINFO, &siginfo));
- #ifdef USE_PLEDGE
- pledge("stdio proc exec", NULL);
- c = 1;
- #endif
- #ifdef USE_CAPSICUM
- c = 1;
- #endif
- if ((a = af_fdopen(STDOUT_FILENO)) == NULL)
- err(EX_DATAERR, "Could not initialize audio codec");
- #ifdef USE_MODE
- if (amode != NULL && af_set(a, "mode", amode) != 1) {
- fprintf(stderr, "%s: Invalid mode %s\n", amode);
- if (af_get(a, "mode", &amode) == 1)
- fprintf(stderr, "Available modes: %s\n", amode);
- exit(EX_USAGE);
- }
- #endif
- #ifdef USE_BITRATE
- (void)af_set(a, "bitrate", bitrate);
- #endif
- #ifdef USE_QUALITY
- (void)af_set(a, "quality", quality);
- #endif
- while (nread(STDIN_FILENO, b, AU_SIZE) == AU_SIZE) {
- IFINFO(info_bytes += AU_SIZE);
- if (au_gethdr(&au, b) != 0)
- errx(EX_DATAERR, "Bad header");
- if (af_set(a, "rate channels", au.au_rate, au.au_chan)
- != 2)
- err(EX_DATAERR,
- "Could not set audio parameters");
- if (af_set(a, "encoding", au.au_enc) != 1) {
- if (cpid > 0)
- abort();
- if (af_get(a, "encoding", &enc) != 1)
- err(EX_SOFTWARE,
- "Could not get desired encoding");
- if (pipe(cpipe) == -1)
- err(EX_OSERR, "Could not create pipe");
- switch (cpid = fork()) {
- case -1:
- err(EX_OSERR, "Could not fork process");
- case 0:
- close(cpipe[0]);
- if (dup2(cpipe[1], STDOUT_FILENO) == -1)
- err(EX_OSERR, "Could not "
- "connect the pipe");
- auconvp(&au, enc, b, bsize);
- err(EX_SOFTWARE,
- "Could not execute auconv");
- default:
- close(cpipe[1]);
- if (dup2(cpipe[0], STDIN_FILENO) == -1)
- err(EX_OSERR, "Could not "
- "connect the pipe");
- break;
- }
- continue;
- }
- #ifdef USE_CAPSICUM
- if (c) {
- if (cap_enter() == -1 && errno != ENOSYS)
- err(EX_OSERR,
- "Could not enter capability mode");
- (void)cap_rights_init(&rights, CAP_READ);
- if (cap_rights_limit(STDIN_FILENO, &rights)
- != 0 && errno != ENOSYS)
- err(EX_OSERR, "Could not limit the "
- "standard input");
- (void)cap_rights_init(&rights, CAP_WRITE,
- CAP_SEEK);
- if (cap_rights_limit(STDOUT_FILENO, &rights)
- != 0 && errno != ENOSYS)
- err(EX_OSERR, "Could not limit the "
- "standard output");
- (void)cap_rights_init(&rights, CAP_WRITE);
- if (cap_rights_limit(STDERR_FILENO, &rights)
- != 0 && errno != ENOSYS)
- err(EX_OSERR, "Could not limit the "
- "standard error");
- c = 0;
- }
- #endif /* USE_CAPSICUM */
- #ifdef USE_PLEDGE
- if (c) {
- pledge("stdio", NULL);
- c = 0;
- }
- #endif
- for (i = AU_SIZE; i < au.au_off; i += r) {
- if ((r = read(STDIN_FILENO, b,
- MIN(bsize, au.au_off - i))) < 0) {
- if (errno == EINTR)
- goto ret;
- err(EX_IOERR, "read error");
- }
- if (r == 0)
- err(EX_DATAERR, "Unexpected EOF");
- IFINFO(info_bytes += r);
- }
- while ((r = read(STDIN_FILENO, b,
- MIN(bsize, au.au_size))) > 0) {
- if (af_write(a, b, r) != r) {
- if (errno == EINTR)
- goto ret;
- err(EX_IOERR, "write error");
- }
- if (au.au_size != UINT32_MAX)
- au.au_size -= r;
- IFINFO(info_bytes += r);
- }
- if (r < 0) {
- if (errno == EINTR)
- goto ret;
- err(EX_IOERR, "read error");
- }
- if (r == 0) { /* EOF */
- ret:
- if (au.au_size > 0 &&
- au.au_size != UINT32_MAX) {
- af_close(a);
- free(b);
- err(EX_DATAERR, "Unexpected EOF");
- }
- break;
- }
- }
- af_close(a);
- free(b);
- return (EX_OK);
- usage:
- c = strlen(getprogname()) + 8;
- (void)fprintf(stderr, "usage: %s"
- #ifdef USE_BITRATE
- " [-B bitrate]"
- #endif
- " [-b buffer-size]"
- #ifdef USE_MODE
- " [-m mode]"
- #endif
- #ifdef USE_QUALITY
- " [-q quality]"
- #endif
- "\n", getprogname());
- return (EX_USAGE);
- }
- void
- sighandle(int sig)
- {
- (void)sigaddset(&sigpend, sig);
- }
- #ifdef SIGINFO
- void
- siginfo(int sig)
- {
- /* au2XXXX: XXXXXXiB processed */
- char b[NAMEMAX + 2 + 8 + 11];
- size_t i;
- i = strlen(getprogname());
- if (i > NAMEMAX) {
- (void)memcpy(b, getprogname(), NAMEMAX - 3);
- (void)memcpy(b + NAMEMAX - 3, "...", 3);
- i = NAMEMAX;
- } else
- (void)memcpy(b, getprogname(), i);
- (void)memcpy(b + i, ": ", 2);
- i += 2;
- i += szwrite(b + i, info_bytes, "B", "iB");
- (void)memcpy(b + i, " processed\n", 11);
- i += 11;
- (void)write(STDERR_FILENO, b, i);
- }
- #endif
|