Annotation of src/usr.bin/midicat/midicat.c, Revision 1.2
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);
1.2 ! deraadt 101: if (ifd == -1) {
1.1 ratchov 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);
1.2 ! deraadt 111: if (ofd == -1) {
1.1 ratchov 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:
1.2 ! deraadt 144: if (pledge("stdio", NULL) == -1)
1.1 ratchov 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;
1.2 ! deraadt 153: if (len == -1) {
1.1 ratchov 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: }