Annotation of src/usr.bin/midicat/midicat.c, Revision 1.1
1.1 ! ratchov 1: /*
! 2: * Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org>
! 3: *
! 4: * Permission to use, copy, modify, and distribute this software for any
! 5: * purpose with or without fee is hereby granted, provided that the above
! 6: * copyright notice and this permission notice appear in all copies.
! 7: *
! 8: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 9: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 10: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 11: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 12: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 13: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 14: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 15: */
! 16: #include <err.h>
! 17: #include <fcntl.h>
! 18: #include <sndio.h>
! 19: #include <stdio.h>
! 20: #include <stdlib.h>
! 21: #include <unistd.h>
! 22: #include <string.h>
! 23:
! 24: char usagestr[] = "usage: midicat [-d] [-i in-file] [-o out-file] "
! 25: "[-q in-port] [-q out-port]\n";
! 26:
! 27: int
! 28: main(int argc, char **argv)
! 29: {
! 30: #define MIDI_BUFSZ 1024
! 31: unsigned char buf[MIDI_BUFSZ];
! 32: struct mio_hdl *ih, *oh;
! 33: char *port0, *port1, *ifile, *ofile;
! 34: int ifd, ofd;
! 35: int dump, c, i, len, n, sep, mode;
! 36:
! 37: dump = 0;
! 38: port0 = port1 = ifile = ofile = NULL;
! 39: ih = oh = NULL;
! 40: ifd = ofd = -1;
! 41:
! 42: while ((c = getopt(argc, argv, "di:o:q:")) != -1) {
! 43: switch (c) {
! 44: case 'd':
! 45: dump = 1;
! 46: break;
! 47: case 'q':
! 48: if (port0 == NULL)
! 49: port0 = optarg;
! 50: else if (port1 == NULL)
! 51: port1 = optarg;
! 52: else {
! 53: fputs("too many -q options\n", stderr);
! 54: return 1;
! 55: }
! 56: break;
! 57: case 'i':
! 58: ifile = optarg;
! 59: break;
! 60: case 'o':
! 61: ofile = optarg;
! 62: break;
! 63: default:
! 64: goto bad_usage;
! 65: }
! 66: }
! 67: argc -= optind;
! 68: argv += optind;
! 69: if (argc != 0) {
! 70: bad_usage:
! 71: fputs(usagestr, stderr);
! 72: return 1;
! 73: }
! 74:
! 75: /* we don't support more than one data flow */
! 76: if (ifile != NULL && ofile != NULL) {
! 77: fputs("-i and -o are exclusive\n", stderr);
! 78: return 1;
! 79: }
! 80:
! 81: /* second port makes sense only for port-to-port transfers */
! 82: if (port1 != NULL && !(ifile == NULL && ofile == NULL)) {
! 83: fputs("too many -q options\n", stderr);
! 84: return 1;
! 85: }
! 86:
! 87: /* if there're neither files nor ports, then we've nothing to do */
! 88: if (port0 == NULL && ifile == NULL && ofile == NULL)
! 89: goto bad_usage;
! 90:
! 91: /* if no port specified, use default one */
! 92: if (port0 == NULL)
! 93: port0 = MIO_PORTANY;
! 94:
! 95: /* open input or output file (if any) */
! 96: if (ifile) {
! 97: if (strcmp(ifile, "-") == 0)
! 98: ifd = STDIN_FILENO;
! 99: else {
! 100: ifd = open(ifile, O_RDONLY, 0);
! 101: if (ifd < 0) {
! 102: perror(ifile);
! 103: return 1;
! 104: }
! 105: }
! 106: } else if (ofile) {
! 107: if (strcmp(ofile, "-") == 0)
! 108: ofd = STDOUT_FILENO;
! 109: else {
! 110: ofd = open(ofile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
! 111: if (ofd < 0) {
! 112: perror(ofile);
! 113: return 1;
! 114: }
! 115: }
! 116: }
! 117:
! 118: /* open first port for input and output (if output needed) */
! 119: if (ofile)
! 120: mode = MIO_IN;
! 121: else if (ifile)
! 122: mode = MIO_OUT;
! 123: else if (port1 == NULL)
! 124: mode = MIO_IN | MIO_OUT;
! 125: else
! 126: mode = MIO_IN;
! 127: ih = mio_open(port0, mode, 0);
! 128: if (ih == NULL) {
! 129: fprintf(stderr, "%s: couldn't open port\n", port0);
! 130: return 1;
! 131: }
! 132:
! 133: /* open second port, output only */
! 134: if (port1 == NULL)
! 135: oh = ih;
! 136: else {
! 137: oh = mio_open(port1, MIO_OUT, 0);
! 138: if (oh == NULL) {
! 139: fprintf(stderr, "%s: couldn't open port\n", port1);
! 140: exit(1);
! 141: }
! 142: }
! 143:
! 144: if (pledge("stdio", NULL) < 0)
! 145: err(1, "pledge");
! 146:
! 147: /* transfer until end-of-file or error */
! 148: for (;;) {
! 149: if (ifile != NULL) {
! 150: len = read(ifd, buf, sizeof(buf));
! 151: if (len == 0)
! 152: break;
! 153: if (len < 0) {
! 154: perror("stdin");
! 155: break;
! 156: }
! 157: } else {
! 158: len = mio_read(ih, buf, sizeof(buf));
! 159: if (len == 0) {
! 160: fprintf(stderr, "%s: disconnected\n", port0);
! 161: break;
! 162: }
! 163: }
! 164: if (ofile != NULL) {
! 165: n = write(ofd, buf, len);
! 166: if (n != len) {
! 167: fprintf(stderr, "%s: short write\n", ofile);
! 168: break;
! 169: }
! 170: } else {
! 171: n = mio_write(oh, buf, len);
! 172: if (n != len) {
! 173: fprintf(stderr, "%s: disconnected\n", port1);
! 174: break;
! 175: }
! 176: }
! 177: if (dump) {
! 178: for (i = 0; i < len; i++) {
! 179: sep = (i % 16 == 15 || i == len - 1) ?
! 180: '\n' : ' ';
! 181: fprintf(stderr, "%02x%c", buf[i], sep);
! 182: }
! 183: }
! 184: }
! 185:
! 186: /* clean-up */
! 187: if (port0)
! 188: mio_close(ih);
! 189: if (port1)
! 190: mio_close(oh);
! 191: if (ifile)
! 192: close(ifd);
! 193: if (ofile)
! 194: close(ofd);
! 195: return 0;
! 196: }