xref: /openbsd/usr.bin/sndiod/sndiod.c (revision 7b639200)
1 /*	$OpenBSD: sndiod.c,v 1.50 2024/12/20 07:35:56 ratchov Exp $	*/
2 /*
3  * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
4  *
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/stat.h>
18 #include <sys/types.h>
19 #include <sys/resource.h>
20 #include <sys/socket.h>
21 
22 #include <err.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <grp.h>
26 #include <limits.h>
27 #include <pwd.h>
28 #include <signal.h>
29 #include <sndio.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 
35 #include "amsg.h"
36 #include "defs.h"
37 #include "dev.h"
38 #include "fdpass.h"
39 #include "file.h"
40 #include "listen.h"
41 #include "midi.h"
42 #include "opt.h"
43 #include "sock.h"
44 #include "utils.h"
45 
46 /*
47  * unprivileged user name
48  */
49 #ifndef SNDIO_USER
50 #define SNDIO_USER	"_sndio"
51 #endif
52 
53 /*
54  * privileged user name
55  */
56 #ifndef SNDIO_PRIV_USER
57 #define SNDIO_PRIV_USER	"_sndiop"
58 #endif
59 
60 /*
61  * priority when run as root
62  */
63 #ifndef SNDIO_PRIO
64 #define SNDIO_PRIO	(-20)
65 #endif
66 
67 /*
68  * sample rate if no ``-r'' is used
69  */
70 #ifndef DEFAULT_RATE
71 #define DEFAULT_RATE	48000
72 #endif
73 
74 /*
75  * block size if neither ``-z'' nor ``-b'' is used
76  */
77 #ifndef DEFAULT_ROUND
78 #define DEFAULT_ROUND	480
79 #endif
80 
81 /*
82  * buffer size if neither ``-z'' nor ``-b'' is used
83  */
84 #ifndef DEFAULT_BUFSZ
85 #define DEFAULT_BUFSZ	7680
86 #endif
87 
88 /*
89  * default device precision
90  */
91 #ifndef DEFAULT_BITS
92 #define DEFAULT_BITS	16
93 #endif
94 
95 void sigint(int);
96 void sighup(int);
97 void opt_ch(int *, int *);
98 void opt_enc(struct aparams *);
99 int opt_mmc(void);
100 int opt_onoff(void);
101 int getword(char *, char **);
102 unsigned int opt_mode(void);
103 void getbasepath(char *);
104 void setsig(void);
105 void unsetsig(void);
106 struct dev *mkdev(char *, struct aparams *,
107     int, int, int, int, int, int);
108 struct port *mkport(char *, int);
109 struct opt *mkopt(char *, struct dev *,
110     int, int, int, int, int, int, int, int);
111 
112 unsigned int log_level = 0;
113 volatile sig_atomic_t quit_flag = 0, reopen_flag = 0;
114 
115 char usagestr[] = "usage: sndiod [-d] [-a flag] [-b nframes] "
116     "[-C min:max] [-c min:max]\n\t"
117     "[-e enc] [-F device] [-f device] [-j flag] [-L addr] [-m mode]\n\t"
118     "[-Q port] [-q port] [-r rate] [-s name] [-t mode] [-U unit]\n\t"
119     "[-v volume] [-w flag] [-z nframes]\n";
120 
121 /*
122  * default audio devices
123  */
124 static char *default_devs[] = {
125 	"rsnd/0", "rsnd/1", "rsnd/2", "rsnd/3",
126 	NULL
127 };
128 
129 /*
130  * default MIDI ports
131  */
132 static char *default_ports[] = {
133 	"rmidi/0", "rmidi/1", "rmidi/2", "rmidi/3",
134 	"rmidi/4", "rmidi/5", "rmidi/6", "rmidi/7",
135 	NULL
136 };
137 
138 /*
139  * SIGINT handler, it raises the quit flag. If the flag is already set,
140  * that means that the last SIGINT was not handled, because the process
141  * is blocked somewhere, so exit.
142  */
143 void
sigint(int s)144 sigint(int s)
145 {
146 	if (quit_flag)
147 		_exit(1);
148 	quit_flag = 1;
149 }
150 
151 /*
152  * SIGHUP handler, it raises the reopen flag, which requests devices
153  * to be reopened.
154  */
155 void
sighup(int s)156 sighup(int s)
157 {
158 	reopen_flag = 1;
159 }
160 
161 void
opt_ch(int * rcmin,int * rcmax)162 opt_ch(int *rcmin, int *rcmax)
163 {
164 	char *next, *end;
165 	long cmin, cmax;
166 
167 	errno = 0;
168 	cmin = strtol(optarg, &next, 10);
169 	if (next == optarg || *next != ':')
170 		goto failed;
171 	cmax = strtol(++next, &end, 10);
172 	if (end == next || *end != '\0')
173 		goto failed;
174 	if (cmin < 0 || cmax < cmin || cmax >= NCHAN_MAX)
175 		goto failed;
176 	*rcmin = cmin;
177 	*rcmax = cmax;
178 	return;
179 failed:
180 	errx(1, "%s: bad channel range", optarg);
181 }
182 
183 void
opt_enc(struct aparams * par)184 opt_enc(struct aparams *par)
185 {
186 	int len;
187 
188 	len = aparams_strtoenc(par, optarg);
189 	if (len == 0 || optarg[len] != '\0')
190 		errx(1, "%s: bad encoding", optarg);
191 }
192 
193 int
opt_mmc(void)194 opt_mmc(void)
195 {
196 	if (strcmp("off", optarg) == 0)
197 		return 0;
198 	if (strcmp("slave", optarg) == 0)
199 		return 1;
200 	errx(1, "%s: off/slave expected", optarg);
201 }
202 
203 int
opt_onoff(void)204 opt_onoff(void)
205 {
206 	if (strcmp("off", optarg) == 0)
207 		return 0;
208 	if (strcmp("on", optarg) == 0)
209 		return 1;
210 	errx(1, "%s: on/off expected", optarg);
211 }
212 
213 int
getword(char * word,char ** str)214 getword(char *word, char **str)
215 {
216 	char *p = *str;
217 
218 	for (;;) {
219 		if (*word == '\0')
220 			break;
221 		if (*word++ != *p++)
222 			return 0;
223 	}
224 	if (*p == ',' || *p == '\0') {
225 		*str = p;
226 		return 1;
227 	}
228 	return 0;
229 }
230 
231 unsigned int
opt_mode(void)232 opt_mode(void)
233 {
234 	unsigned int mode = 0;
235 	char *p = optarg;
236 
237 	for (;;) {
238 		if (getword("play", &p)) {
239 			mode |= MODE_PLAY;
240 		} else if (getword("rec", &p)) {
241 			mode |= MODE_REC;
242 		} else if (getword("mon", &p)) {
243 			mode |= MODE_MON;
244 		} else if (getword("midi", &p)) {
245 			mode |= MODE_MIDIMASK;
246 		} else
247 			errx(1, "%s: bad mode", optarg);
248 		if (*p == '\0')
249 			break;
250 		p++;
251 	}
252 	if (mode == 0)
253 		errx(1, "empty mode");
254 	return mode;
255 }
256 
257 /*
258  * Open all devices. Possibly switch to the new devices if they have higher
259  * priorities than the current ones.
260  */
261 static void
reopen_devs(void)262 reopen_devs(void)
263 {
264 	struct opt *o;
265 	struct dev *d, *a;
266 
267 	for (o = opt_list; o != NULL; o = o->next) {
268 
269 		/* skip unused logical devices and ones with fixed hardware */
270 		if (o->refcnt == 0 || strcmp(o->name, o->dev->name) == 0)
271 			continue;
272 
273 		/* circulate to the device with the highest prio */
274 		a = o->alt_first;
275 		for (d = a; d->alt_next != a; d = d->alt_next) {
276 			if (d->num > o->alt_first->num)
277 				o->alt_first = d;
278 		}
279 
280 		/* switch to the first working one, in pririty order */
281 		d = o->alt_first;
282 		while (d != o->dev) {
283 			if (opt_setdev(o, d))
284 				break;
285 			d = d->alt_next;
286 		}
287 	}
288 
289 	/*
290 	 * retry to open the remaining devices that are not used but need
291 	 * to stay open (ex. '-a on')
292 	 */
293 	for (d = dev_list; d != NULL; d = d->next) {
294 		if (d->refcnt > 0 && d->pstate == DEV_CFG)
295 			dev_open(d);
296 	}
297 }
298 
299 /*
300  * For each port, open the alt with the highest priority and switch to it
301  */
302 static void
reopen_ports(void)303 reopen_ports(void)
304 {
305 	struct port *p, *a, *apri;
306 	int inuse;
307 
308 	for (p = port_list; p != NULL; p = a->next) {
309 
310 		/* skip unused ports */
311 		inuse = 0;
312 		a = p;
313 		while (1) {
314 			if (midi_rxmask(a->midi) || a->midi->txmask)
315 				inuse = 1;
316 			if (a->alt_next == p)
317 				break;
318 			a = a->alt_next;
319 		}
320 		if (!inuse)
321 			continue;
322 
323 		/* open the alt with the highest prio */
324 		apri = port_alt_ref(p->num);
325 
326 		/* switch to it */
327 		a = p;
328 		while (1) {
329 			if (a != apri) {
330 				midi_migrate(a->midi, apri->midi);
331 				port_unref(a);
332 			}
333 			if (a->alt_next == p)
334 				break;
335 			a = a->alt_next;
336 		}
337 	}
338 }
339 
340 void
setsig(void)341 setsig(void)
342 {
343 	struct sigaction sa;
344 
345 	quit_flag = 0;
346 	reopen_flag = 0;
347 	sigfillset(&sa.sa_mask);
348 	sa.sa_flags = SA_RESTART;
349 	sa.sa_handler = sigint;
350 	if (sigaction(SIGINT, &sa, NULL) == -1)
351 		err(1, "sigaction(int) failed");
352 	if (sigaction(SIGTERM, &sa, NULL) == -1)
353 		err(1, "sigaction(term) failed");
354 	sa.sa_handler = sighup;
355 	if (sigaction(SIGHUP, &sa, NULL) == -1)
356 		err(1, "sigaction(hup) failed");
357 }
358 
359 void
unsetsig(void)360 unsetsig(void)
361 {
362 	struct sigaction sa;
363 
364 	sigfillset(&sa.sa_mask);
365 	sa.sa_flags = SA_RESTART;
366 	sa.sa_handler = SIG_DFL;
367 	if (sigaction(SIGHUP, &sa, NULL) == -1)
368 		err(1, "unsetsig(hup): sigaction failed");
369 	if (sigaction(SIGTERM, &sa, NULL) == -1)
370 		err(1, "unsetsig(term): sigaction failed");
371 	if (sigaction(SIGINT, &sa, NULL) == -1)
372 		err(1, "unsetsig(int): sigaction failed");
373 }
374 
375 void
getbasepath(char * base)376 getbasepath(char *base)
377 {
378 	uid_t uid;
379 	struct stat sb;
380 	mode_t mask, omask;
381 
382 	uid = geteuid();
383 	if (uid == 0) {
384 		mask = 022;
385 		snprintf(base, SOCKPATH_MAX, SOCKPATH_DIR);
386 	} else {
387 		mask = 077;
388 		snprintf(base, SOCKPATH_MAX, SOCKPATH_DIR "-%u", uid);
389 	}
390 	omask = umask(mask);
391 	if (mkdir(base, 0777) == -1) {
392 		if (errno != EEXIST)
393 			err(1, "mkdir(\"%s\")", base);
394 	}
395 	umask(omask);
396 	if (stat(base, &sb) == -1)
397 		err(1, "stat(\"%s\")", base);
398 	if (!S_ISDIR(sb.st_mode))
399 		errx(1, "%s is not a directory", base);
400 	if (sb.st_uid != uid || (sb.st_mode & mask) != 0)
401 		errx(1, "%s has wrong permissions", base);
402 }
403 
404 struct dev *
mkdev(char * path,struct aparams * par,int mode,int bufsz,int round,int rate,int hold,int autovol)405 mkdev(char *path, struct aparams *par,
406     int mode, int bufsz, int round, int rate, int hold, int autovol)
407 {
408 	struct dev *d;
409 
410 	for (d = dev_list; d != NULL; d = d->next) {
411 		if (strcmp(d->path, path) == 0)
412 			return d;
413 	}
414 	if (!bufsz && !round) {
415 		round = DEFAULT_ROUND;
416 		bufsz = DEFAULT_BUFSZ;
417 	} else if (!bufsz) {
418 		bufsz = round * 2;
419 	} else if (!round)
420 		round = bufsz / 2;
421 	d = dev_new(path, par, mode, bufsz, round, rate, hold, autovol);
422 	if (d == NULL)
423 		exit(1);
424 	return d;
425 }
426 
427 struct port *
mkport(char * path,int hold)428 mkport(char *path, int hold)
429 {
430 	struct port *c;
431 
432 	for (c = port_list; c != NULL; c = c->next) {
433 		if (strcmp(c->path, path) == 0)
434 			return c;
435 	}
436 	c = port_new(path, MODE_MIDIMASK, hold);
437 	if (c == NULL)
438 		exit(1);
439 	return c;
440 }
441 
442 struct opt *
mkopt(char * path,struct dev * d,int pmin,int pmax,int rmin,int rmax,int mode,int vol,int mmc,int dup)443 mkopt(char *path, struct dev *d,
444     int pmin, int pmax, int rmin, int rmax,
445     int mode, int vol, int mmc, int dup)
446 {
447 	struct opt *o;
448 
449 	o = opt_new(d, path, pmin, pmax, rmin, rmax,
450 	    MIDI_TO_ADATA(vol), mmc, dup, mode);
451 	if (o == NULL)
452 		return NULL;
453 	dev_adjpar(d, o->mode, o->pmax, o->rmax);
454 	return o;
455 }
456 
457 static void
dounveil(char * name,char * prefix,char * path_prefix)458 dounveil(char *name, char *prefix, char *path_prefix)
459 {
460 	size_t prefix_len;
461 	char path[PATH_MAX];
462 
463 	prefix_len = strlen(prefix);
464 
465 	if (strncmp(name, prefix, prefix_len) != 0)
466 		errx(1, "%s: unsupported device or port format", name);
467 	snprintf(path, sizeof(path), "%s%s", path_prefix, name + prefix_len);
468 	if (unveil(path, "rw") == -1)
469 		err(1, "unveil %s", path);
470 }
471 
472 static int
start_helper(int background)473 start_helper(int background)
474 {
475 	struct dev *d;
476 	struct port *p;
477 	struct passwd *pw;
478 	int s[2];
479 	pid_t pid;
480 
481 	if (geteuid() == 0) {
482 		if ((pw = getpwnam(SNDIO_PRIV_USER)) == NULL)
483 			errx(1, "unknown user %s", SNDIO_PRIV_USER);
484 	} else
485 		pw = NULL;
486 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1) {
487 		perror("socketpair");
488 		return 0;
489 	}
490 	pid = fork();
491 	if (pid	== -1) {
492 		perror("fork");
493 		return 0;
494 	}
495 	if (pid == 0) {
496 		setproctitle("helper");
497 		close(s[0]);
498 		if (fdpass_new(s[1], &helper_fileops) == NULL)
499 			return 0;
500 		if (background) {
501 			log_flush();
502 			log_level = 0;
503 			if (daemon(0, 0) == -1)
504 				err(1, "daemon");
505 		}
506 		if (pw != NULL) {
507 			if (setgroups(1, &pw->pw_gid) ||
508 			    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
509 			    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
510 				err(1, "cannot drop privileges");
511 		}
512 		for (d = dev_list; d != NULL; d = d->next) {
513 			dounveil(d->path, "rsnd/", "/dev/audio");
514 			dounveil(d->path, "rsnd/", "/dev/audioctl");
515 		}
516 		for (p = port_list; p != NULL; p = p->next) {
517 			dounveil(p->path, "rmidi/", "/dev/rmidi");
518 		}
519 		if (pledge("stdio sendfd rpath wpath", NULL) == -1)
520 			err(1, "pledge");
521 		while (file_poll())
522 			; /* nothing */
523 		exit(0);
524 	} else {
525 		close(s[1]);
526 		if (fdpass_new(s[0], &worker_fileops) == NULL)
527 			return 0;
528 	}
529 	return 1;
530 }
531 
532 static void
stop_helper(void)533 stop_helper(void)
534 {
535 	if (fdpass_peer)
536 		fdpass_close(fdpass_peer);
537 }
538 
539 int
main(int argc,char ** argv)540 main(int argc, char **argv)
541 {
542 	int c, i, background, unit;
543 	int pmin, pmax, rmin, rmax;
544 	char base[SOCKPATH_MAX], path[SOCKPATH_MAX];
545 	unsigned int mode, dup, mmc, vol;
546 	unsigned int hold, autovol, bufsz, round, rate;
547 	const char *str;
548 	struct aparams par;
549 	struct opt *o;
550 	struct dev *d, *dev_first, *dev_next;
551 	struct port *p, *port_first, *port_next;
552 	struct listen *l;
553 	struct passwd *pw;
554 	struct tcpaddr {
555 		char *host;
556 		struct tcpaddr *next;
557 	} *tcpaddr_list, *ta;
558 
559 	atexit(log_flush);
560 
561 	/*
562 	 * global options defaults
563 	 */
564 	vol = 127;
565 	dup = 1;
566 	mmc = 0;
567 	hold = 0;
568 	autovol = 0;
569 	bufsz = 0;
570 	round = 0;
571 	rate = DEFAULT_RATE;
572 	unit = 0;
573 	background = 1;
574 	pmin = 0;
575 	pmax = 1;
576 	rmin = 0;
577 	rmax = 1;
578 	par.bits = DEFAULT_BITS;
579 	par.bps = APARAMS_BPS(par.bits);
580 	par.le = ADATA_LE;
581 	par.sig = 1;
582 	par.msb = 0;
583 	mode = MODE_PLAY | MODE_REC;
584 	dev_first = dev_next = NULL;
585 	port_first = port_next = NULL;
586 	tcpaddr_list = NULL;
587 	d = NULL;
588 	p = NULL;
589 
590 	slot_array_init();
591 
592 	while ((c = getopt(argc, argv,
593 	    "a:b:c:C:de:F:f:j:L:m:Q:q:r:s:t:U:v:w:x:z:")) != -1) {
594 		switch (c) {
595 		case 'd':
596 			log_level++;
597 			background = 0;
598 			break;
599 		case 'U':
600 			unit = strtonum(optarg, 0, 15, &str);
601 			if (str)
602 				errx(1, "%s: unit number is %s", optarg, str);
603 			break;
604 		case 'L':
605 			ta = xmalloc(sizeof(struct tcpaddr));
606 			ta->host = optarg;
607 			ta->next = tcpaddr_list;
608 			tcpaddr_list = ta;
609 			break;
610 		case 'm':
611 			mode = opt_mode();
612 			break;
613 		case 'j':
614 			dup = opt_onoff();
615 			break;
616 		case 't':
617 			mmc = opt_mmc();
618 			break;
619 		case 'c':
620 			opt_ch(&pmin, &pmax);
621 			break;
622 		case 'C':
623 			opt_ch(&rmin, &rmax);
624 			break;
625 		case 'e':
626 			opt_enc(&par);
627 			break;
628 		case 'r':
629 			rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str);
630 			if (str)
631 				errx(1, "%s: rate is %s", optarg, str);
632 			break;
633 		case 'v':
634 			vol = strtonum(optarg, 0, MIDI_MAXCTL, &str);
635 			if (str)
636 				errx(1, "%s: volume is %s", optarg, str);
637 			break;
638 		case 's':
639 			if (d == NULL) {
640 				for (i = 0; default_devs[i] != NULL; i++) {
641 					mkdev(default_devs[i], &par, 0,
642 					    bufsz, round, rate, 0, autovol);
643 				}
644 				d = dev_list;
645 			}
646 			if (mkopt(optarg, d, pmin, pmax, rmin, rmax,
647 				mode, vol, mmc, dup) == NULL)
648 				return 1;
649 			break;
650 		case 'q':
651 			p = mkport(optarg, hold);
652 			/* create new circulate list */
653 			port_first = port_next = p;
654 			break;
655 		case 'Q':
656 			if (p == NULL)
657 				errx(1, "-Q %s: no ports defined", optarg);
658 			p = mkport(optarg, hold);
659 			/* add to circulate list */
660 			p->alt_next = port_next;
661 			port_first->alt_next = p;
662 			port_next = p;
663 			break;
664 		case 'a':
665 			hold = opt_onoff();
666 			break;
667 		case 'w':
668 			autovol = opt_onoff();
669 			break;
670 		case 'b':
671 			bufsz = strtonum(optarg, 1, RATE_MAX, &str);
672 			if (str)
673 				errx(1, "%s: buffer size is %s", optarg, str);
674 			break;
675 		case 'z':
676 			round = strtonum(optarg, 1, SHRT_MAX, &str);
677 			if (str)
678 				errx(1, "%s: block size is %s", optarg, str);
679 			break;
680 		case 'f':
681 			d = mkdev(optarg, &par, 0, bufsz, round,
682 			    rate, hold, autovol);
683 			/* create new circulate list */
684 			dev_first = dev_next = d;
685 			break;
686 		case 'F':
687 			if (d == NULL)
688 				errx(1, "-F %s: no devices defined", optarg);
689 			d = mkdev(optarg, &par, 0, bufsz, round,
690 			    rate, hold, autovol);
691 			/* add to circulate list */
692 			d->alt_next = dev_next;
693 			dev_first->alt_next = d;
694 			dev_next = d;
695 			break;
696 		default:
697 			fputs(usagestr, stderr);
698 			return 1;
699 		}
700 	}
701 	argc -= optind;
702 	argv += optind;
703 	if (argc > 0) {
704 		fputs(usagestr, stderr);
705 		return 1;
706 	}
707 	if (port_list == NULL) {
708 		for (i = 0; default_ports[i] != NULL; i++)
709 			mkport(default_ports[i], 0);
710 	}
711 	if (dev_list == NULL) {
712 		for (i = 0; default_devs[i] != NULL; i++) {
713 			mkdev(default_devs[i], &par, 0,
714 			    bufsz, round, rate, 0, autovol);
715 		}
716 	}
717 
718 	/*
719 	 * Add default sub-device (if none) backed by the last device
720 	 */
721 	o = opt_byname("default");
722 	if (o == NULL) {
723 		o = mkopt("default", dev_list, pmin, pmax, rmin, rmax,
724 		    mode, vol, 0, dup);
725 		if (o == NULL)
726 			return 1;
727 	}
728 
729 	/*
730 	 * For each device create an anonymous sub-device using
731 	 * the "default" sub-device as template
732 	 */
733 	for (d = dev_list; d != NULL; d = d->next) {
734 		if (opt_new(d, NULL, o->pmin, o->pmax, o->rmin, o->rmax,
735 			o->maxweight, o->mtc != NULL, o->dup, o->mode) == NULL)
736 			return 1;
737 		dev_adjpar(d, o->mode, o->pmax, o->rmax);
738 	}
739 
740 	setsig();
741 	filelist_init();
742 
743 	if (!start_helper(background))
744 		return 1;
745 
746 	if (geteuid() == 0) {
747 		if ((pw = getpwnam(SNDIO_USER)) == NULL)
748 			errx(1, "unknown user %s", SNDIO_USER);
749 	} else
750 		pw = NULL;
751 	getbasepath(base);
752 	snprintf(path, SOCKPATH_MAX, "%s/" SOCKPATH_FILE "%u", base, unit);
753 	if (!listen_new_un(path))
754 		return 1;
755 	for (ta = tcpaddr_list; ta != NULL; ta = ta->next) {
756 		if (!listen_new_tcp(ta->host, AUCAT_PORT + unit))
757 			return 1;
758 	}
759 	for (l = listen_list; l != NULL; l = l->next) {
760 		if (!listen_init(l))
761 			return 1;
762 	}
763 	midi_init();
764 	for (p = port_list; p != NULL; p = p->next) {
765 		if (!port_init(p))
766 			return 1;
767 	}
768 	for (d = dev_list; d != NULL; d = d->next) {
769 		if (!dev_init(d))
770 			return 1;
771 	}
772 	for (o = opt_list; o != NULL; o = o->next)
773 		opt_init(o);
774 	if (background) {
775 		log_flush();
776 		log_level = 0;
777 		if (daemon(0, 0) == -1)
778 			err(1, "daemon");
779 	}
780 	if (pw != NULL) {
781 		if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) == -1)
782 			err(1, "setpriority");
783 		if (chroot(pw->pw_dir) == -1 || chdir("/") == -1)
784 			err(1, "cannot chroot to %s", pw->pw_dir);
785 		if (setgroups(1, &pw->pw_gid) == -1 ||
786 		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 ||
787 		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1 )
788 			err(1, "cannot drop privileges");
789 	}
790 	if (tcpaddr_list) {
791 		if (pledge("stdio audio recvfd unix inet", NULL) == -1)
792 			err(1, "pledge");
793 	} else {
794 		if (pledge("stdio audio recvfd unix", NULL) == -1)
795 			err(1, "pledge");
796 	}
797 
798 	for (;;) {
799 		if (quit_flag)
800 			break;
801 		if (reopen_flag) {
802 			reopen_flag = 0;
803 			reopen_devs();
804 			reopen_ports();
805 		}
806 		if (!fdpass_peer)
807 			break;
808 		if (!file_poll())
809 			break;
810 	}
811 	stop_helper();
812 	while (listen_list != NULL)
813 		listen_close(listen_list);
814 	while (sock_list != NULL)
815 		sock_close(sock_list);
816 	for (o = opt_list; o != NULL; o = o->next)
817 		opt_done(o);
818 	for (d = dev_list; d != NULL; d = d->next)
819 		dev_done(d);
820 	for (p = port_list; p != NULL; p = p->next)
821 		port_done(p);
822 	while (file_poll())
823 		; /* nothing */
824 	midi_done();
825 
826 	while (opt_list)
827 		opt_del(opt_list);
828 	while (dev_list)
829 		dev_del(dev_list);
830 	while (port_list)
831 		port_del(port_list);
832 	while (tcpaddr_list) {
833 		ta = tcpaddr_list;
834 		tcpaddr_list = ta->next;
835 		xfree(ta);
836 	}
837 	filelist_done();
838 	unsetsig();
839 	return 0;
840 }
841