Annotation of src/usr.bin/aucat/aucat.c, Revision 1.136
1.136 ! ratchov 1: /* $OpenBSD: aucat.c,v 1.135 2012/05/23 19:25:11 ratchov Exp $ */
1.1 kstailey 2: /*
1.15 ratchov 3: * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
1.1 kstailey 4: *
1.15 ratchov 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 <sys/param.h>
18: #include <sys/queue.h>
1.55 ratchov 19: #include <sys/stat.h>
1.62 ratchov 20: #include <sys/types.h>
1.86 ratchov 21: #include <sys/resource.h>
1.13 uwe 22:
1.15 ratchov 23: #include <err.h>
1.55 ratchov 24: #include <errno.h>
1.1 kstailey 25: #include <fcntl.h>
1.55 ratchov 26: #include <limits.h>
1.86 ratchov 27: #include <pwd.h>
1.15 ratchov 28: #include <signal.h>
1.135 ratchov 29: #include <sndio.h>
1.1 kstailey 30: #include <stdio.h>
1.4 millert 31: #include <stdlib.h>
1.8 david 32: #include <string.h>
1.1 kstailey 33: #include <unistd.h>
34:
1.62 ratchov 35: #include "abuf.h"
1.112 ratchov 36: #include "amsg.h"
1.15 ratchov 37: #include "aparams.h"
38: #include "aproc.h"
1.62 ratchov 39: #include "conf.h"
40: #include "dev.h"
1.28 ratchov 41: #include "listen.h"
1.61 ratchov 42: #include "midi.h"
43: #include "opt.h"
1.62 ratchov 44: #include "wav.h"
1.78 ratchov 45: #ifdef DEBUG
46: #include "dbg.h"
47: #endif
1.11 jaredy 48:
1.86 ratchov 49: /*
50: * unprivileged user name
51: */
52: #define SNDIO_USER "_sndio"
53:
54: /*
55: * priority when run as root
56: */
57: #define SNDIO_PRIO (-20)
58:
1.61 ratchov 59: #define PROG_AUCAT "aucat"
1.129 ratchov 60: #define PROG_SNDIOD "sndiod"
1.61 ratchov 61:
1.108 ratchov 62: /*
63: * sample rate if no ``-r'' is used
64: */
65: #ifndef DEFAULT_RATE
1.132 ratchov 66: #define DEFAULT_RATE 48000
1.108 ratchov 67: #endif
68:
1.120 ratchov 69: /*
1.133 ratchov 70: * block size if neither ``-z'' nor ``-b'' is used
1.120 ratchov 71: */
72: #ifndef DEFAULT_ROUND
1.133 ratchov 73: #define DEFAULT_ROUND 960
74: #endif
75:
76: /*
77: * buffer size if neither ``-z'' nor ``-b'' is used
78: */
79: #ifndef DEFAULT_BUFSZ
80: #define DEFAULT_BUFSZ 7860
1.120 ratchov 81: #endif
82:
1.125 ratchov 83: /*
84: * default device in server mode
85: */
86: #ifndef DEFAULT_DEV
87: #define DEFAULT_DEV "rsnd/0"
88: #endif
89:
1.78 ratchov 90: #ifdef DEBUG
1.120 ratchov 91: volatile sig_atomic_t debug_level = 1;
1.78 ratchov 92: #endif
1.111 deraadt 93: volatile sig_atomic_t quit_flag = 0;
1.7 deraadt 94:
1.130 ratchov 95: char aucat_usage[] = "usage: " PROG_AUCAT " [-dn] [-b nframes] "
1.120 ratchov 96: "[-C min:max] [-c min:max] [-e enc]\n\t"
1.129 ratchov 97: "[-f device] [-h fmt] [-i file] [-j flag] [-m mode] [-o file]\n\t"
98: "[-q port] [-r rate] [-t mode] [-v volume] [-w flag] [-x policy]\n\t"
99: "[-z nframes]\n";
100:
1.130 ratchov 101: char sndiod_usage[] = "usage: " PROG_SNDIOD " [-dM] [-a flag] [-b nframes] "
1.129 ratchov 102: "[-C min:max] [-c min:max] [-e enc]\n\t"
103: "[-f device] [-j flag] [-L addr] [-m mode] [-q port] [-r rate]\n\t"
104: "[-s name] [-t mode] [-U unit] [-v volume] [-w flag] [-x policy]\n\t"
105: "[-z nframes]\n";
1.120 ratchov 106:
1.28 ratchov 107: /*
108: * SIGINT handler, it raises the quit flag. If the flag is already set,
109: * that means that the last SIGINT was not handled, because the process
1.62 ratchov 110: * is blocked somewhere, so exit.
1.28 ratchov 111: */
112: void
113: sigint(int s)
114: {
115: if (quit_flag)
116: _exit(1);
117: quit_flag = 1;
118: }
1.22 ratchov 119:
1.78 ratchov 120: #ifdef DEBUG
121: /*
122: * Increase debug level on SIGUSR1.
123: */
124: void
125: sigusr1(int s)
126: {
127: if (debug_level < 4)
128: debug_level++;
129: }
130:
131: /*
132: * Decrease debug level on SIGUSR2.
133: */
134: void
135: sigusr2(int s)
136: {
137: if (debug_level > 0)
138: debug_level--;
139: }
140: #endif
1.15 ratchov 141:
142: void
143: opt_ch(struct aparams *par)
144: {
1.76 ratchov 145: char *next, *end;
146: long cmin, cmax;
1.13 uwe 147:
1.76 ratchov 148: errno = 0;
149: cmin = strtol(optarg, &next, 10);
150: if (next == optarg || *next != ':')
151: goto failed;
152: cmax = strtol(++next, &end, 10);
153: if (end == next || *end != '\0')
154: goto failed;
155: if (cmin < 0 || cmax < cmin || cmax > NCHAN_MAX)
156: goto failed;
157: par->cmin = cmin;
158: par->cmax = cmax;
159: return;
160: failed:
161: errx(1, "%s: bad channel range", optarg);
1.15 ratchov 162: }
1.13 uwe 163:
1.15 ratchov 164: void
165: opt_enc(struct aparams *par)
166: {
1.28 ratchov 167: int len;
168:
169: len = aparams_strtoenc(par, optarg);
170: if (len == 0 || optarg[len] != '\0')
171: errx(1, "%s: bad encoding", optarg);
1.15 ratchov 172: }
1.4 millert 173:
1.15 ratchov 174: int
175: opt_hdr(void)
176: {
177: if (strcmp("auto", optarg) == 0)
178: return HDR_AUTO;
179: if (strcmp("raw", optarg) == 0)
180: return HDR_RAW;
181: if (strcmp("wav", optarg) == 0)
182: return HDR_WAV;
1.35 ratchov 183: errx(1, "%s: bad header specification", optarg);
1.1 kstailey 184: }
185:
1.22 ratchov 186: int
1.74 ratchov 187: opt_mmc(void)
188: {
189: if (strcmp("off", optarg) == 0)
190: return 0;
191: if (strcmp("slave", optarg) == 0)
192: return 1;
193: errx(1, "%s: bad MMC mode", optarg);
194: }
195:
196: int
1.90 ratchov 197: opt_onoff(void)
1.84 ratchov 198: {
199: if (strcmp("off", optarg) == 0)
200: return 0;
201: if (strcmp("on", optarg) == 0)
202: return 1;
203: errx(1, "%s: bad join/expand setting", optarg);
204: }
205:
206: int
1.22 ratchov 207: opt_xrun(void)
208: {
209: if (strcmp("ignore", optarg) == 0)
210: return XRUN_IGNORE;
211: if (strcmp("sync", optarg) == 0)
212: return XRUN_SYNC;
213: if (strcmp("error", optarg) == 0)
214: return XRUN_ERROR;
1.73 ratchov 215: errx(1, "%s: bad underrun/overrun policy", optarg);
1.22 ratchov 216: }
217:
1.134 ratchov 218: unsigned int
1.43 ratchov 219: opt_mode(void)
220: {
1.134 ratchov 221: unsigned int mode = 0;
1.83 ratchov 222: char *p = optarg;
223: size_t len;
224:
1.104 ratchov 225: for (p = optarg; *p != '\0'; p++) {
1.83 ratchov 226: len = strcspn(p, ",");
227: if (strncmp("play", p, len) == 0) {
228: mode |= MODE_PLAY;
229: } else if (strncmp("rec", p, len) == 0) {
230: mode |= MODE_REC;
231: } else if (strncmp("mon", p, len) == 0) {
232: mode |= MODE_MON;
1.120 ratchov 233: } else if (strncmp("midi", p, len) == 0) {
234: mode |= MODE_MIDIMASK;
1.83 ratchov 235: } else
236: errx(1, "%s: bad mode", optarg);
237: p += len;
238: if (*p == '\0')
239: break;
240: }
241: if (mode == 0)
242: errx(1, "empty mode");
243: return mode;
1.43 ratchov 244: }
245:
1.113 ratchov 246: void
1.61 ratchov 247: setsig(void)
248: {
249: struct sigaction sa;
250:
251: quit_flag = 0;
252: sigfillset(&sa.sa_mask);
253: sa.sa_flags = SA_RESTART;
254: sa.sa_handler = sigint;
255: if (sigaction(SIGINT, &sa, NULL) < 0)
1.68 ratchov 256: err(1, "sigaction(int) failed");
1.61 ratchov 257: if (sigaction(SIGTERM, &sa, NULL) < 0)
1.68 ratchov 258: err(1, "sigaction(term) failed");
1.61 ratchov 259: if (sigaction(SIGHUP, &sa, NULL) < 0)
1.68 ratchov 260: err(1, "sigaction(hup) failed");
1.78 ratchov 261: #ifdef DEBUG
262: sa.sa_handler = sigusr1;
263: if (sigaction(SIGUSR1, &sa, NULL) < 0)
264: err(1, "sigaction(usr1) failed");
265: sa.sa_handler = sigusr2;
266: if (sigaction(SIGUSR2, &sa, NULL) < 0)
267: err(1, "sigaction(usr2) failed1n");
268: #endif
1.61 ratchov 269: }
270:
271: void
272: unsetsig(void)
273: {
274: struct sigaction sa;
275:
276: sigfillset(&sa.sa_mask);
277: sa.sa_flags = SA_RESTART;
278: sa.sa_handler = SIG_DFL;
1.78 ratchov 279: #ifdef DEBUG
280: if (sigaction(SIGUSR2, &sa, NULL) < 0)
281: err(1, "unsetsig(usr2): sigaction failed");
282: if (sigaction(SIGUSR1, &sa, NULL) < 0)
283: err(1, "unsetsig(usr1): sigaction failed");
284: #endif
1.61 ratchov 285: if (sigaction(SIGHUP, &sa, NULL) < 0)
1.68 ratchov 286: err(1, "unsetsig(hup): sigaction failed\n");
1.61 ratchov 287: if (sigaction(SIGTERM, &sa, NULL) < 0)
1.68 ratchov 288: err(1, "unsetsig(term): sigaction failed\n");
1.61 ratchov 289: if (sigaction(SIGINT, &sa, NULL) < 0)
1.68 ratchov 290: err(1, "unsetsig(int): sigaction failed\n");
1.61 ratchov 291: }
292:
293: void
294: getbasepath(char *base, size_t size)
295: {
296: uid_t uid;
297: struct stat sb;
1.86 ratchov 298: mode_t mask;
1.61 ratchov 299:
300: uid = geteuid();
1.86 ratchov 301: if (uid == 0) {
302: mask = 022;
303: snprintf(base, PATH_MAX, "/tmp/aucat");
304: } else {
305: mask = 077;
306: snprintf(base, PATH_MAX, "/tmp/aucat-%u", uid);
307: }
308: if (mkdir(base, 0777 & ~mask) < 0) {
1.61 ratchov 309: if (errno != EEXIST)
310: err(1, "mkdir(\"%s\")", base);
311: }
312: if (stat(base, &sb) < 0)
313: err(1, "stat(\"%s\")", base);
1.86 ratchov 314: if (sb.st_uid != uid || (sb.st_mode & mask) != 0)
1.61 ratchov 315: errx(1, "%s has wrong permissions", base);
316: }
317:
318: void
1.86 ratchov 319: privdrop(void)
320: {
321: struct passwd *pw;
322: struct stat sb;
323:
324: if ((pw = getpwnam(SNDIO_USER)) == NULL)
1.105 deraadt 325: errx(1, "unknown user %s", SNDIO_USER);
1.86 ratchov 326: if (stat(pw->pw_dir, &sb) < 0)
327: err(1, "stat(\"%s\")", pw->pw_dir);
328: if (sb.st_uid != 0 || (sb.st_mode & 022) != 0)
329: errx(1, "%s has wrong permissions", pw->pw_dir);
330: if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) < 0)
331: err(1, "setpriority");
332: if (setgroups(1, &pw->pw_gid) ||
333: setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
334: setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
335: err(1, "cannot drop privileges");
336: }
337:
1.120 ratchov 338: struct dev *
339: mkdev(char *path, int mode, int bufsz, int round, int hold, int autovol)
1.61 ratchov 340: {
1.120 ratchov 341: struct dev *d;
342:
343: if (path) {
344: for (d = dev_list; d != NULL; d = d->next) {
345: if (d->reqmode & (MODE_LOOP | MODE_THRU))
346: continue;
347: if (strcmp(d->path, path) == 0)
348: return d;
349: }
350: } else {
351: if (dev_list)
352: return dev_list;
1.135 ratchov 353: path = SIO_DEVANY;
1.120 ratchov 354: }
1.133 ratchov 355: if (!bufsz && !round) {
356: round = DEFAULT_ROUND;
357: bufsz = DEFAULT_BUFSZ;
358: } else if (!bufsz) {
1.132 ratchov 359: bufsz = round * 2;
1.120 ratchov 360: } else if (!round)
1.132 ratchov 361: round = bufsz / 2;
1.125 ratchov 362: d = dev_new(path, mode, bufsz, round, hold, autovol);
363: if (d == NULL)
364: exit(1);
365: return d;
1.120 ratchov 366: }
367:
368: struct opt *
369: mkopt(char *path, struct dev *d, struct aparams *rpar, struct aparams *ppar,
370: int mode, int vol, int mmc, int join)
371: {
372: struct opt *o;
373:
374: if (d->reqmode & MODE_LOOP)
375: errx(1, "%s: can't attach to loopback", path);
376: if (d->reqmode & MODE_THRU)
377: mode = MODE_MIDIMASK;
378: if (!rpar->rate)
379: ppar->rate = rpar->rate = DEFAULT_RATE;
380: o = opt_new(path, d, rpar, ppar, MIDI_TO_ADATA(vol), mmc, join, mode);
381: if (o == NULL)
382: errx(1, "%s: couldn't create subdev", path);
383: dev_adjpar(d, o->mode, rpar, ppar);
384: return o;
1.61 ratchov 385: }
386:
1.1 kstailey 387: int
1.120 ratchov 388: main(int argc, char **argv)
1.1 kstailey 389: {
1.122 ratchov 390: char *prog, *optstr, *usagestr;
1.128 ratchov 391: int c, background, unit, active;
1.92 ratchov 392: char base[PATH_MAX], path[PATH_MAX];
1.134 ratchov 393: unsigned int mode, hdr, xrun, rate, join, mmc, vol;
394: unsigned int hold, autovol, bufsz, round;
1.76 ratchov 395: const char *str;
1.120 ratchov 396: struct aparams ppar, rpar;
1.92 ratchov 397: struct dev *d, *dnext;
1.120 ratchov 398: struct listen *l;
399: struct wav *w;
1.19 ratchov 400:
1.92 ratchov 401: /*
402: * global options defaults
403: */
1.120 ratchov 404: hdr = HDR_AUTO;
405: xrun = XRUN_IGNORE;
406: vol = MIDI_MAXCTL;
1.124 ratchov 407: join = 1;
1.120 ratchov 408: mmc = 0;
1.124 ratchov 409: hold = 0;
410: autovol = 1;
1.120 ratchov 411: bufsz = 0;
412: round = 0;
413: unit = 0;
414: background = 0;
415: aparams_init(&ppar, 0, 1, DEFAULT_RATE);
416: aparams_init(&rpar, 0, 1, DEFAULT_RATE);
1.123 ratchov 417: mode = MODE_MIDIMASK | MODE_PLAY | MODE_REC;
1.120 ratchov 418:
419: #ifdef DEBUG
420: atexit(dbg_flush);
421: #endif
422: setsig();
423: filelist_init();
424:
425: prog = strrchr(argv[0], '/');
426: if (prog == NULL)
427: prog = argv[0];
428: else
429: prog++;
430: if (strcmp(prog, PROG_AUCAT) == 0) {
1.136 ! ratchov 431: optstr = "b:c:C:de:f:h:i:j:m:no:q:r:t:v:w:x:z:";
1.120 ratchov 432: usagestr = aucat_usage;
1.129 ratchov 433: } else if (strcmp(prog, PROG_SNDIOD) == 0) {
434: optstr = "a:b:c:C:de:f:j:L:m:Mq:r:s:t:U:v:w:x:z:";
435: usagestr = sndiod_usage;
436: background = 1;
437: hold = 0;
1.120 ratchov 438: } else {
439: fprintf(stderr, "%s: can't determine program to run\n", prog);
440: return 1;
441: }
1.92 ratchov 442:
1.120 ratchov 443: while ((c = getopt(argc, argv, optstr)) != -1) {
1.15 ratchov 444: switch (c) {
1.69 ratchov 445: case 'd':
1.78 ratchov 446: #ifdef DEBUG
1.120 ratchov 447: if (debug_level < 4)
1.78 ratchov 448: debug_level++;
449: #endif
1.129 ratchov 450: background = 0;
1.51 ratchov 451: break;
1.92 ratchov 452: case 'U':
1.128 ratchov 453: if (listen_list)
454: errx(1, "-U must come before -L");
1.92 ratchov 455: unit = strtonum(optarg, 0, MIDI_MAXCTL, &str);
456: if (str)
457: errx(1, "%s: unit number is %s", optarg, str);
458: break;
1.113 ratchov 459: case 'L':
1.122 ratchov 460: listen_new_tcp(optarg, AUCAT_PORT + unit);
1.113 ratchov 461: break;
1.43 ratchov 462: case 'm':
1.120 ratchov 463: mode = opt_mode();
1.43 ratchov 464: break;
1.15 ratchov 465: case 'h':
1.120 ratchov 466: hdr = opt_hdr();
1.15 ratchov 467: break;
1.22 ratchov 468: case 'x':
1.120 ratchov 469: xrun = opt_xrun();
1.22 ratchov 470: break;
1.84 ratchov 471: case 'j':
1.120 ratchov 472: join = opt_onoff();
1.84 ratchov 473: break;
1.74 ratchov 474: case 't':
1.120 ratchov 475: mmc = opt_mmc();
1.74 ratchov 476: break;
1.15 ratchov 477: case 'c':
1.120 ratchov 478: opt_ch(&ppar);
1.15 ratchov 479: break;
480: case 'C':
1.120 ratchov 481: opt_ch(&rpar);
1.15 ratchov 482: break;
483: case 'e':
1.120 ratchov 484: opt_enc(&ppar);
485: aparams_copyenc(&rpar, &ppar);
1.15 ratchov 486: break;
487: case 'r':
1.92 ratchov 488: rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str);
1.76 ratchov 489: if (str)
490: errx(1, "%s: rate is %s", optarg, str);
1.120 ratchov 491: ppar.rate = rpar.rate = rate;
1.15 ratchov 492: break;
1.35 ratchov 493: case 'v':
1.120 ratchov 494: vol = strtonum(optarg, 0, MIDI_MAXCTL, &str);
1.76 ratchov 495: if (str)
496: errx(1, "%s: volume is %s", optarg, str);
1.35 ratchov 497: break;
1.15 ratchov 498: case 'i':
1.120 ratchov 499: d = mkdev(NULL, 0, bufsz, round, 1, autovol);
500: w = wav_new_in(&wav_ops, d,
501: mode & (MODE_PLAY | MODE_MIDIOUT), optarg,
502: hdr, &ppar, xrun, vol, mmc, join);
503: if (w == NULL)
504: errx(1, "%s: couldn't create stream", optarg);
505: dev_adjpar(d, w->mode, NULL, &w->hpar);
506: break;
507: case 'o':
508: d = mkdev(NULL, 0, bufsz, round, 1, autovol);
509: w = wav_new_out(&wav_ops, d,
510: mode & (MODE_RECMASK | MODE_MIDIIN), optarg,
511: hdr, &rpar, xrun, mmc, join);
512: if (w == NULL)
513: errx(1, "%s: couldn't create stream", optarg);
514: dev_adjpar(d, w->mode, &w->hpar, NULL);
1.15 ratchov 515: break;
1.120 ratchov 516: case 's':
1.131 ratchov 517: if ((d = dev_list) == NULL) {
518: d = mkdev(DEFAULT_DEV, 0, bufsz, round,
519: hold, autovol);
520: }
521: mkopt(optarg, d, &rpar, &ppar, mode, vol, mmc, join);
1.120 ratchov 522: /* XXX: set device rate, if never set */
1.42 ratchov 523: break;
1.120 ratchov 524: case 'q':
525: d = mkdev(NULL, mode, bufsz, round, 1, autovol);
526: if (!devctl_add(d, optarg, MODE_MIDIMASK))
527: errx(1, "%s: can't open port", optarg);
528: d->reqmode |= MODE_MIDIMASK;
1.92 ratchov 529: break;
530: case 'a':
1.120 ratchov 531: hold = opt_onoff();
1.83 ratchov 532: break;
1.115 ratchov 533: case 'w':
1.120 ratchov 534: autovol = opt_onoff();
1.4 millert 535: break;
1.28 ratchov 536: case 'b':
1.120 ratchov 537: bufsz = strtonum(optarg, 1, RATE_MAX * 5, &str);
1.76 ratchov 538: if (str)
539: errx(1, "%s: buffer size is %s", optarg, str);
1.28 ratchov 540: break;
1.74 ratchov 541: case 'z':
1.120 ratchov 542: round = strtonum(optarg, 1, SHRT_MAX, &str);
1.76 ratchov 543: if (str)
544: errx(1, "%s: block size is %s", optarg, str);
1.74 ratchov 545: break;
1.92 ratchov 546: case 'f':
1.120 ratchov 547: mkdev(optarg, 0, bufsz, round, hold, autovol);
548: break;
549: case 'n':
550: mkdev("loopback", MODE_LOOP, bufsz, round, 1, autovol);
551: break;
552: case 'M':
1.127 ratchov 553: mkdev("midithru", MODE_THRU, 0, 0, hold, 0);
1.92 ratchov 554: break;
1.11 jaredy 555: default:
1.120 ratchov 556: fputs(usagestr, stderr);
1.15 ratchov 557: exit(1);
1.4 millert 558: }
559: }
560: argc -= optind;
561: argv += optind;
1.92 ratchov 562: if (argc > 0) {
1.120 ratchov 563: fputs(usagestr, stderr);
1.102 ratchov 564: exit(1);
1.15 ratchov 565: }
1.125 ratchov 566: if (wav_list) {
1.128 ratchov 567: if (opt_list || listen_list)
1.125 ratchov 568: errx(1, "-io not allowed in server mode");
569: if ((d = dev_list) && d->next)
570: errx(1, "only one device allowed in non-server mode");
571: if ((d->reqmode & MODE_THRU) && d->ctl_list == NULL) {
1.120 ratchov 572: if (!devctl_add(d, "default", MODE_MIDIMASK))
573: errx(1, "%s: can't open port", optarg);
574: d->reqmode |= MODE_MIDIMASK;
1.125 ratchov 575: }
576: } else {
577: if (dev_list == NULL)
578: mkdev(DEFAULT_DEV, 0, bufsz, round, hold, autovol);
579: for (d = dev_list; d != NULL; d = d->next) {
580: if (opt_byname("default", d->num))
581: continue;
582: mkopt("default", d, &rpar, &ppar, mode, vol, mmc, join);
1.92 ratchov 583: }
1.42 ratchov 584: }
1.128 ratchov 585: if (opt_list) {
1.61 ratchov 586: getbasepath(base, sizeof(base));
1.122 ratchov 587: snprintf(path, PATH_MAX, "%s/%s%u", base, AUCAT_PATH, unit);
1.120 ratchov 588: listen_new_un(path);
589: if (geteuid() == 0)
590: privdrop();
591: }
592: for (w = wav_list; w != NULL; w = w->next) {
593: if (!wav_init(w))
594: exit(1);
1.55 ratchov 595: }
1.120 ratchov 596: for (d = dev_list; d != NULL; d = d->next) {
597: if (!dev_init(d))
598: exit(1);
599: if (d->autostart && (d->mode & MODE_AUDIOMASK))
1.126 ratchov 600: dev_mmcstart(d);
1.56 ratchov 601: }
1.120 ratchov 602: for (l = listen_list; l != NULL; l = l->next) {
603: if (!listen_init(l))
604: exit(1);
1.98 ratchov 605: }
1.120 ratchov 606: if (background) {
1.107 ratchov 607: #ifdef DEBUG
1.98 ratchov 608: debug_level = 0;
609: dbg_flush();
1.107 ratchov 610: #endif
1.98 ratchov 611: if (daemon(0, 0) < 0)
1.56 ratchov 612: err(1, "daemon");
1.15 ratchov 613: }
1.13 uwe 614:
1.15 ratchov 615: /*
1.62 ratchov 616: * Loop, start audio.
1.15 ratchov 617: */
1.28 ratchov 618: for (;;) {
1.90 ratchov 619: if (quit_flag)
1.28 ratchov 620: break;
1.92 ratchov 621: active = 0;
622: for (d = dev_list; d != NULL; d = dnext) {
623: dnext = d->next;
624: if (!dev_run(d))
625: goto fatal;
1.127 ratchov 626: if (d->refcnt > 0)
1.92 ratchov 627: active = 1;
628: }
629: if (dev_list == NULL)
1.50 ratchov 630: break;
1.128 ratchov 631: if (!opt_list && !active)
1.83 ratchov 632: break;
1.50 ratchov 633: if (!file_poll())
634: break;
1.34 ratchov 635: }
1.92 ratchov 636: fatal:
1.120 ratchov 637: while (listen_list != NULL)
638: file_close(&listen_list->file);
1.110 ratchov 639:
1.90 ratchov 640: /*
641: * give a chance to drain
642: */
1.96 ratchov 643: for (d = dev_list; d != NULL; d = d->next)
644: dev_drain(d);
1.90 ratchov 645: while (file_poll())
646: ; /* nothing */
1.96 ratchov 647:
648: while (dev_list)
649: dev_del(dev_list);
1.83 ratchov 650: filelist_done();
1.128 ratchov 651: if (opt_list) {
1.86 ratchov 652: if (rmdir(base) < 0 && errno != ENOTEMPTY && errno != EPERM)
1.55 ratchov 653: warn("rmdir(\"%s\")", base);
654: }
1.61 ratchov 655: unsetsig();
656: return 0;
1.1 kstailey 657: }