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