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