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