//roarvio.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011-2015 * * This file is part of roarclients a part of RoarAudio, * a cross-platform sound system for both, home and professional use. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * as published by the Free Software Foundation. * * RoarAudio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ int g_verbose = 0; #define ROAR_DBG_INFOVAR g_verbose #include #include #include #include enum action { READ, WRITE, PASS, EXPLAIN }; void usage (const char * progname) { fprintf(stderr, "Usage: %s [OPTIONS]... FILE [FILE]\n", progname); fprintf(stderr, "\nOptions:\n\n"); fprintf(stderr, " -h --help - This help.\n" " --verbose - Be verbose. Can be used multiple times.\n" " --read - Reading mode (like 'cat file').\n" " --write - Writing mode (like 'cat > file').\n" " --pass - Passing mode (like 'cat infile > outfile').\n" " --explain - Explain VIO object.\n"); } ssize_t do_explain (struct roar_vio_calls * cur) { struct roar_sockname sockname; int have_sockname; int need_space, need_space2; int level = 0; int fh; const char * name; const char * codec; const char * content_type; while (cur != NULL) { if ( roar_vio_ctl(cur, ROAR_VIO_CTL_GET_NAME, &name) == -1 ) name = "UNKNOWN"; if ( g_verbose ) { if ( roar_vio_ctl(cur, ROAR_VIO_CTL_GET_MIMETYPE, &content_type) == -1 ) content_type = "UNKNOWN"; codec = roar_codec2str(roar_mime2codec(content_type)); if ( roar_vio_ctl(cur, ROAR_VIO_CTL_GET_FH, &fh) == -1 ) fh = -1; if ( g_verbose > 1 ) { if ( roar_vio_ctl(cur, ROAR_VIO_CTL_GET_PEERNAME, &sockname) == -1 ) { have_sockname = 0; } else { have_sockname = 1; } } else { have_sockname = 0; } } else { content_type = "UNKNOWN"; codec = "UNKNOWN"; fh = -1; have_sockname = 0; } printf("%i: %s", level, name); if ( fh != -1 || !!strcasecmp(codec, "UNKNOWN") || !!strcasecmp(content_type, "UNKNOWN") || have_sockname ) { need_space = 0; printf(" ("); if ( fh != -1 ) { printf("fh=%i", fh); need_space = 1; } if ( have_sockname ) { need_space2 = 0; printf("%ssocket={", need_space ? ", " : ""); need_space2 = 1; switch (sockname.type) { case ROAR_SOCKET_TYPE_UNIX: printf("af=UNIX"); break; case ROAR_SOCKET_TYPE_DECNET: printf("af=DECnet"); break; case ROAR_SOCKET_TYPE_INET: printf("af=INET"); break; case ROAR_SOCKET_TYPE_INET6: printf("af=INET6"); break; default: need_space2 = 0; break; } if ( sockname.addr != NULL ) { printf("%saddr=\"%s\"", need_space2 ? ", " : "", sockname.addr); need_space2 = 1; } if ( sockname.port ) { printf("%sport=%i", need_space2 ? ", " : "", sockname.port); need_space2 = 1; } printf("}"); need_space = 1; } if ( !!strcasecmp(codec, "UNKNOWN") ) { printf("%scodec=%s", need_space ? ", " : "", codec); need_space = 1; } if ( !!strcmp(content_type, "UNKNOWN") ) { printf("%scontent-type=\"%s\"", need_space ? ", " : "", content_type); need_space = 1; } printf(")"); } printf("\n"); level++; if ( have_sockname ) if ( sockname.addr != NULL ) roar_mm_free(sockname.addr); if ( roar_vio_ctl(cur, ROAR_VIO_CTL_GET_NEXT, &cur) == -1 ) cur = NULL; } roar_error = ROAR_ERROR_NONE; return 0; } int main (int argc, char * argv[]) { struct roar_vio_defaults def; struct roar_vio_calls vio0, vio1; enum action action = READ; ssize_t written = -1; int i; const char * k; const char * file0 = NULL; const char * file1 = NULL; int o_flags = -1; int ret = 0; for (i = 1; i < argc; i++) { k = argv[i]; if ( !strcmp(k, "-h") || !strcmp(k, "--help") ) { usage(argv[0]); return 0; } else if ( !strcmp(k, "--read") ) { action = READ; } else if ( !strcmp(k, "--write") ) { action = WRITE; } else if ( !strcmp(k, "--pass") ) { action = PASS; } else if ( !strcmp(k, "--explain") ) { action = EXPLAIN; } else if ( !strcmp(k, "--verbose") ) { g_verbose++; } else if ( file0 == NULL ) { file0 = k; } else if ( file1 == NULL ) { file1 = k; } else { ROAR_ERR("Too many parameters or unknown parameter: %s", k); usage(argv[0]); return 1; } } if ( file0 == NULL ) { usage(argv[0]); return 1; } if ( (file1 != NULL && action != PASS) || (action == PASS && file1 == NULL) ) { usage(argv[0]); return 1; } switch (action) { case READ: case PASS: case EXPLAIN: o_flags = O_RDONLY; break; case WRITE: o_flags = O_WRONLY|O_CREAT|O_TRUNC; break; } if ( o_flags == -1 ) { ROAR_ERR("o_flags unset, very bad. This should never happen."); return 1; } if ( roar_vio_dstr_init_defaults(&def, ROAR_VIO_DEF_TYPE_NONE, o_flags, 0644) == -1 ) { ROAR_ERR("Can not init DSTR defaults. Bad."); return 1; } if ( roar_vio_open_dstr(&vio0, file0, &def, 1) == -1 ) { ROAR_ERR("Can not open file: %s: %s", file0, roar_error2str(roar_error)); return 1; } if ( action == PASS ) { if ( roar_vio_dstr_init_defaults(&def, ROAR_VIO_DEF_TYPE_NONE, O_WRONLY|O_CREAT|O_TRUNC, 0644) == -1 ) { ROAR_ERR("Can not init DSTR defaults. Bad."); roar_vio_close(&vio0); return 1; } if ( roar_vio_open_dstr(&vio1, file1, &def, 1) == -1 ) { ROAR_ERR("Can not open file: %s: %s", file1, roar_error2str(roar_error)); roar_vio_close(&vio0); return 1; } } switch (action) { case READ: written = roar_vio_copy_data(roar_stdout, &vio0); break; case WRITE: written = roar_vio_copy_data(&vio0, roar_stdin); break; case PASS: written = roar_vio_copy_data(&vio1, &vio0); break; case EXPLAIN: if ( (written = do_explain(&vio0)) == -1 ) ret = 4; break; } if ( written == -1 ) { ROAR_ERR("Can not push data: %s", roar_error2str(roar_error)); } roar_vio_close(&vio0); if ( file1 != NULL ) roar_vio_close(&vio1); return ret; } //ll