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