Annotation of src/usr.bin/sndiod/sndiod.c, Revision 1.41
1.41 ! ratchov 1: /* $OpenBSD: sndiod.c,v 1.40 2020/04/25 05:35:52 ratchov Exp $ */
1.1 ratchov 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>
1.18 ratchov 20: #include <sys/socket.h>
1.1 ratchov 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"
1.18 ratchov 38: #include "fdpass.h"
1.1 ratchov 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: /*
1.18 ratchov 54: * privileged user name
55: */
56: #ifndef SNDIO_PRIV_USER
57: #define SNDIO_PRIV_USER "_sndiop"
58: #endif
59:
60: /*
1.1 ratchov 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
1.37 ratchov 78: #define DEFAULT_ROUND 480
1.1 ratchov 79: #endif
80:
81: /*
82: * buffer size if neither ``-z'' nor ``-b'' is used
83: */
84: #ifndef DEFAULT_BUFSZ
1.8 dcoppa 85: #define DEFAULT_BUFSZ 7680
1.1 ratchov 86: #endif
87:
1.5 ratchov 88: void sigint(int);
1.36 ratchov 89: void sighup(int);
1.5 ratchov 90: void opt_ch(int *, int *);
91: void opt_enc(struct aparams *);
92: int opt_mmc(void);
93: int opt_onoff(void);
94: int getword(char *, char **);
95: unsigned int opt_mode(void);
1.31 ratchov 96: void getbasepath(char *);
1.5 ratchov 97: void setsig(void);
98: void unsetsig(void);
99: struct dev *mkdev(char *, struct aparams *,
100: int, int, int, int, int, int);
1.27 ratchov 101: struct port *mkport(char *, int);
1.5 ratchov 102: struct opt *mkopt(char *, struct dev *,
103: int, int, int, int, int, int, int, int);
1.1 ratchov 104:
105: unsigned int log_level = 0;
1.36 ratchov 106: volatile sig_atomic_t quit_flag = 0, reopen_flag = 0;
1.1 ratchov 107:
108: char usagestr[] = "usage: sndiod [-d] [-a flag] [-b nframes] "
1.36 ratchov 109: "[-C min:max] [-c min:max]\n\t"
110: "[-e enc] [-F device] [-f device] [-j flag] [-L addr] [-m mode]\n\t"
111: "[-Q port] [-q port] [-r rate] [-s name] [-t mode] [-U unit]\n\t"
112: "[-v volume] [-w flag] [-z nframes]\n";
1.1 ratchov 113:
114: /*
1.40 ratchov 115: * default audio devices
116: */
117: static char *default_devs[] = {
118: "rsnd/0", "rsnd/1", "rsnd/2", "rsnd/3",
119: NULL
120: };
121:
122: /*
1.39 ratchov 123: * default MIDI ports
124: */
125: static char *default_ports[] = {
126: "rmidi/0", "rmidi/1", "rmidi/2", "rmidi/3",
127: "rmidi/4", "rmidi/5", "rmidi/6", "rmidi/7",
128: NULL
129: };
130:
131: /*
1.1 ratchov 132: * SIGINT handler, it raises the quit flag. If the flag is already set,
133: * that means that the last SIGINT was not handled, because the process
134: * is blocked somewhere, so exit.
135: */
136: void
137: sigint(int s)
138: {
139: if (quit_flag)
140: _exit(1);
141: quit_flag = 1;
142: }
143:
1.36 ratchov 144: /*
145: * SIGHUP handler, it raises the reopen flag, which requests devices
146: * to be reopened.
147: */
148: void
149: sighup(int s)
150: {
151: reopen_flag = 1;
152: }
153:
1.1 ratchov 154: void
155: opt_ch(int *rcmin, int *rcmax)
156: {
157: char *next, *end;
158: long cmin, cmax;
159:
160: errno = 0;
161: cmin = strtol(optarg, &next, 10);
162: if (next == optarg || *next != ':')
163: goto failed;
164: cmax = strtol(++next, &end, 10);
165: if (end == next || *end != '\0')
166: goto failed;
167: if (cmin < 0 || cmax < cmin || cmax >= NCHAN_MAX)
168: goto failed;
169: *rcmin = cmin;
170: *rcmax = cmax;
171: return;
172: failed:
173: errx(1, "%s: bad channel range", optarg);
174: }
175:
176: void
177: opt_enc(struct aparams *par)
178: {
179: int len;
180:
181: len = aparams_strtoenc(par, optarg);
182: if (len == 0 || optarg[len] != '\0')
183: errx(1, "%s: bad encoding", optarg);
184: }
185:
186: int
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: off/slave expected", optarg);
194: }
195:
196: int
197: opt_onoff(void)
198: {
199: if (strcmp("off", optarg) == 0)
200: return 0;
201: if (strcmp("on", optarg) == 0)
202: return 1;
203: errx(1, "%s: on/off expected", optarg);
204: }
205:
1.4 ratchov 206: int
207: getword(char *word, char **str)
208: {
209: char *p = *str;
210:
211: for (;;) {
212: if (*word == '\0')
213: break;
214: if (*word++ != *p++)
215: return 0;
216: }
217: if (*p == ',' || *p == '\0') {
218: *str = p;
219: return 1;
220: }
221: return 0;
222: }
223:
1.1 ratchov 224: unsigned int
225: opt_mode(void)
226: {
227: unsigned int mode = 0;
228: char *p = optarg;
229:
1.4 ratchov 230: for (;;) {
231: if (getword("play", &p)) {
1.1 ratchov 232: mode |= MODE_PLAY;
1.4 ratchov 233: } else if (getword("rec", &p)) {
1.1 ratchov 234: mode |= MODE_REC;
1.4 ratchov 235: } else if (getword("mon", &p)) {
1.1 ratchov 236: mode |= MODE_MON;
1.4 ratchov 237: } else if (getword("midi", &p)) {
1.1 ratchov 238: mode |= MODE_MIDIMASK;
1.4 ratchov 239: } else
1.1 ratchov 240: errx(1, "%s: bad mode", optarg);
241: if (*p == '\0')
242: break;
1.4 ratchov 243: p++;
1.1 ratchov 244: }
245: if (mode == 0)
246: errx(1, "empty mode");
247: return mode;
248: }
249:
250: void
251: setsig(void)
252: {
253: struct sigaction sa;
254:
255: quit_flag = 0;
1.36 ratchov 256: reopen_flag = 0;
1.1 ratchov 257: sigfillset(&sa.sa_mask);
258: sa.sa_flags = SA_RESTART;
259: sa.sa_handler = sigint;
1.35 ratchov 260: if (sigaction(SIGINT, &sa, NULL) == -1)
1.1 ratchov 261: err(1, "sigaction(int) failed");
1.35 ratchov 262: if (sigaction(SIGTERM, &sa, NULL) == -1)
1.1 ratchov 263: err(1, "sigaction(term) failed");
1.36 ratchov 264: sa.sa_handler = sighup;
1.35 ratchov 265: if (sigaction(SIGHUP, &sa, NULL) == -1)
1.1 ratchov 266: err(1, "sigaction(hup) failed");
267: }
268:
269: void
270: unsetsig(void)
271: {
272: struct sigaction sa;
273:
274: sigfillset(&sa.sa_mask);
275: sa.sa_flags = SA_RESTART;
276: sa.sa_handler = SIG_DFL;
1.35 ratchov 277: if (sigaction(SIGHUP, &sa, NULL) == -1)
1.29 ratchov 278: err(1, "unsetsig(hup): sigaction failed");
1.35 ratchov 279: if (sigaction(SIGTERM, &sa, NULL) == -1)
1.29 ratchov 280: err(1, "unsetsig(term): sigaction failed");
1.35 ratchov 281: if (sigaction(SIGINT, &sa, NULL) == -1)
1.29 ratchov 282: err(1, "unsetsig(int): sigaction failed");
1.1 ratchov 283: }
284:
285: void
1.31 ratchov 286: getbasepath(char *base)
1.1 ratchov 287: {
288: uid_t uid;
289: struct stat sb;
1.14 ratchov 290: mode_t mask, omask;
1.1 ratchov 291:
292: uid = geteuid();
293: if (uid == 0) {
294: mask = 022;
1.10 ratchov 295: snprintf(base, SOCKPATH_MAX, SOCKPATH_DIR);
1.1 ratchov 296: } else {
297: mask = 077;
1.10 ratchov 298: snprintf(base, SOCKPATH_MAX, SOCKPATH_DIR "-%u", uid);
1.1 ratchov 299: }
1.14 ratchov 300: omask = umask(mask);
1.35 ratchov 301: if (mkdir(base, 0777) == -1) {
1.1 ratchov 302: if (errno != EEXIST)
303: err(1, "mkdir(\"%s\")", base);
304: }
1.28 ratchov 305: umask(omask);
1.35 ratchov 306: if (stat(base, &sb) == -1)
1.1 ratchov 307: err(1, "stat(\"%s\")", base);
1.30 ratchov 308: if (!S_ISDIR(sb.st_mode))
309: errx(1, "%s is not a directory", base);
1.1 ratchov 310: if (sb.st_uid != uid || (sb.st_mode & mask) != 0)
311: errx(1, "%s has wrong permissions", base);
312: }
313:
314: struct dev *
315: mkdev(char *path, struct aparams *par,
316: int mode, int bufsz, int round, int rate, int hold, int autovol)
317: {
318: struct dev *d;
319:
320: for (d = dev_list; d != NULL; d = d->next) {
1.41 ! ratchov 321: if (d->alt_list->next == NULL &&
! 322: strcmp(d->alt_list->name, path) == 0)
1.1 ratchov 323: return d;
324: }
325: if (!bufsz && !round) {
326: round = DEFAULT_ROUND;
327: bufsz = DEFAULT_BUFSZ;
328: } else if (!bufsz) {
329: bufsz = round * 2;
330: } else if (!round)
331: round = bufsz / 2;
332: d = dev_new(path, par, mode, bufsz, round, rate, hold, autovol);
333: if (d == NULL)
334: exit(1);
335: return d;
336: }
337:
1.27 ratchov 338: struct port *
339: mkport(char *path, int hold)
340: {
341: struct port *c;
342:
343: for (c = port_list; c != NULL; c = c->next) {
1.36 ratchov 344: if (c->path_list->next == NULL &&
345: strcmp(c->path_list->str, path) == 0)
1.27 ratchov 346: return c;
347: }
348: c = port_new(path, MODE_MIDIMASK, hold);
349: if (c == NULL)
350: exit(1);
351: return c;
352: }
353:
1.1 ratchov 354: struct opt *
355: mkopt(char *path, struct dev *d,
356: int pmin, int pmax, int rmin, int rmax,
357: int mode, int vol, int mmc, int dup)
358: {
359: struct opt *o;
360:
1.33 ratchov 361: o = opt_new(d, path, pmin, pmax, rmin, rmax,
1.1 ratchov 362: MIDI_TO_ADATA(vol), mmc, dup, mode);
363: if (o == NULL)
1.26 ratchov 364: return NULL;
1.31 ratchov 365: dev_adjpar(d, o->mode, o->pmax, o->rmax);
1.1 ratchov 366: return o;
367: }
368:
1.34 ratchov 369: static void
370: dounveil(char *name, char *prefix, char *path_prefix)
371: {
372: size_t prefix_len;
373: char path[PATH_MAX];
374:
375: prefix_len = strlen(prefix);
376:
377: if (strncmp(name, prefix, prefix_len) != 0)
378: errx(1, "%s: unsupported device or port format", name);
379: snprintf(path, sizeof(path), "%s%s", path_prefix, name + prefix_len);
1.35 ratchov 380: if (unveil(path, "rw") == -1)
1.34 ratchov 381: err(1, "unveil");
382: }
383:
1.32 ratchov 384: static int
385: start_helper(int background)
386: {
1.34 ratchov 387: struct dev *d;
1.41 ! ratchov 388: struct dev_alt *da;
1.34 ratchov 389: struct port *p;
1.32 ratchov 390: struct passwd *pw;
1.36 ratchov 391: struct name *n;
1.32 ratchov 392: int s[2];
393: pid_t pid;
394:
395: if (geteuid() == 0) {
396: if ((pw = getpwnam(SNDIO_PRIV_USER)) == NULL)
397: errx(1, "unknown user %s", SNDIO_PRIV_USER);
398: } else
399: pw = NULL;
1.35 ratchov 400: if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1) {
1.32 ratchov 401: perror("socketpair");
402: return 0;
403: }
404: pid = fork();
405: if (pid == -1) {
406: log_puts("can't fork\n");
407: return 0;
408: }
409: if (pid == 0) {
410: setproctitle("helper");
411: close(s[0]);
412: if (fdpass_new(s[1], &helper_fileops) == NULL)
413: return 0;
414: if (background) {
415: log_flush();
416: log_level = 0;
1.35 ratchov 417: if (daemon(0, 0) == -1)
1.32 ratchov 418: err(1, "daemon");
419: }
420: if (pw != NULL) {
421: if (setgroups(1, &pw->pw_gid) ||
422: setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
423: setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
424: err(1, "cannot drop privileges");
425: }
1.36 ratchov 426: for (d = dev_list; d != NULL; d = d->next) {
1.41 ! ratchov 427: for (da = d->alt_list; da != NULL; da = da->next) {
! 428: dounveil(da->name, "rsnd/", "/dev/audio");
! 429: dounveil(da->name, "rsnd/", "/dev/audioctl");
1.38 ratchov 430: }
1.36 ratchov 431: }
432: for (p = port_list; p != NULL; p = p->next) {
433: for (n = p->path_list; n != NULL; n = n->next)
434: dounveil(n->str, "rmidi/", "/dev/rmidi");
435: }
1.35 ratchov 436: if (pledge("stdio sendfd rpath wpath", NULL) == -1)
1.32 ratchov 437: err(1, "pledge");
438: while (file_poll())
439: ; /* nothing */
440: exit(0);
441: } else {
442: close(s[1]);
443: if (fdpass_new(s[0], &worker_fileops) == NULL)
444: return 0;
445: }
446: return 1;
447: }
448:
449: static void
450: stop_helper(void)
451: {
452: if (fdpass_peer)
453: fdpass_close(fdpass_peer);
454: }
455:
1.1 ratchov 456: int
457: main(int argc, char **argv)
458: {
1.40 ratchov 459: int c, i, background, unit, devindex;
1.1 ratchov 460: int pmin, pmax, rmin, rmax;
1.25 ratchov 461: char base[SOCKPATH_MAX], path[SOCKPATH_MAX];
1.1 ratchov 462: unsigned int mode, dup, mmc, vol;
463: unsigned int hold, autovol, bufsz, round, rate;
464: const char *str;
465: struct aparams par;
466: struct dev *d;
467: struct port *p;
468: struct listen *l;
1.17 ratchov 469: struct passwd *pw;
1.25 ratchov 470: struct tcpaddr {
471: char *host;
472: struct tcpaddr *next;
473: } *tcpaddr_list, *ta;
1.1 ratchov 474:
475: atexit(log_flush);
476:
477: /*
478: * global options defaults
479: */
480: vol = 118;
481: dup = 1;
482: mmc = 0;
483: hold = 0;
484: autovol = 1;
485: bufsz = 0;
486: round = 0;
487: rate = DEFAULT_RATE;
488: unit = 0;
489: background = 1;
490: pmin = 0;
491: pmax = 1;
492: rmin = 0;
493: rmax = 1;
494: aparams_init(&par);
495: mode = MODE_PLAY | MODE_REC;
1.25 ratchov 496: tcpaddr_list = NULL;
1.40 ratchov 497: devindex = 0;
1.1 ratchov 498:
1.36 ratchov 499: while ((c = getopt(argc, argv,
500: "a:b:c:C:de:F:f:j:L:m:Q:q:r:s:t:U:v:w:x:z:")) != -1) {
1.1 ratchov 501: switch (c) {
502: case 'd':
503: log_level++;
504: background = 0;
505: break;
506: case 'U':
507: unit = strtonum(optarg, 0, 15, &str);
508: if (str)
509: errx(1, "%s: unit number is %s", optarg, str);
510: break;
511: case 'L':
1.25 ratchov 512: ta = xmalloc(sizeof(struct tcpaddr));
513: ta->host = optarg;
514: ta->next = tcpaddr_list;
515: tcpaddr_list = ta;
1.1 ratchov 516: break;
517: case 'm':
518: mode = opt_mode();
519: break;
520: case 'j':
521: dup = opt_onoff();
522: break;
523: case 't':
524: mmc = opt_mmc();
525: break;
526: case 'c':
527: opt_ch(&pmin, &pmax);
528: break;
529: case 'C':
530: opt_ch(&rmin, &rmax);
531: break;
532: case 'e':
533: opt_enc(&par);
534: break;
535: case 'r':
536: rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str);
537: if (str)
538: errx(1, "%s: rate is %s", optarg, str);
539: break;
540: case 'v':
541: vol = strtonum(optarg, 0, MIDI_MAXCTL, &str);
542: if (str)
543: errx(1, "%s: volume is %s", optarg, str);
544: break;
545: case 's':
546: if ((d = dev_list) == NULL) {
1.40 ratchov 547: d = mkdev(default_devs[devindex++], &par, 0,
548: bufsz, round, rate, hold, autovol);
1.1 ratchov 549: }
1.26 ratchov 550: if (mkopt(optarg, d, pmin, pmax, rmin, rmax,
551: mode, vol, mmc, dup) == NULL)
552: return 1;
1.1 ratchov 553: break;
554: case 'q':
1.27 ratchov 555: mkport(optarg, hold);
1.1 ratchov 556: break;
1.36 ratchov 557: case 'Q':
558: if (port_list == NULL)
559: errx(1, "-Q %s: no ports defined", optarg);
560: namelist_add(&port_list->path_list, optarg);
561: break;
1.1 ratchov 562: case 'a':
563: hold = opt_onoff();
564: break;
565: case 'w':
566: autovol = opt_onoff();
567: break;
568: case 'b':
569: bufsz = strtonum(optarg, 1, RATE_MAX, &str);
570: if (str)
571: errx(1, "%s: buffer size is %s", optarg, str);
572: break;
573: case 'z':
574: round = strtonum(optarg, 1, SHRT_MAX, &str);
575: if (str)
576: errx(1, "%s: block size is %s", optarg, str);
577: break;
578: case 'f':
1.28 ratchov 579: mkdev(optarg, &par, 0, bufsz, round,
580: rate, hold, autovol);
1.40 ratchov 581: devindex = -1;
1.1 ratchov 582: break;
1.36 ratchov 583: case 'F':
1.41 ! ratchov 584: if ((d = dev_list) == NULL)
1.36 ratchov 585: errx(1, "-F %s: no devices defined", optarg);
1.41 ! ratchov 586: if (!dev_addname(d, optarg))
! 587: exit(1);
1.36 ratchov 588: break;
1.1 ratchov 589: default:
590: fputs(usagestr, stderr);
591: return 1;
592: }
593: }
594: argc -= optind;
595: argv += optind;
596: if (argc > 0) {
597: fputs(usagestr, stderr);
598: return 1;
1.39 ratchov 599: }
600: if (port_list == NULL) {
601: for (i = 0; default_ports[i] != NULL; i++)
602: mkport(default_ports[i], 0);
1.1 ratchov 603: }
1.40 ratchov 604: if (devindex != -1) {
605: for (i = devindex; default_devs[i] != NULL; i++) {
606: mkdev(default_devs[i], &par, 0,
607: bufsz, round, rate, 0, autovol);
608: }
609: }
1.1 ratchov 610: for (d = dev_list; d != NULL; d = d->next) {
1.33 ratchov 611: if (opt_byname(d, "default"))
1.1 ratchov 612: continue;
1.26 ratchov 613: if (mkopt("default", d, pmin, pmax, rmin, rmax,
614: mode, vol, mmc, dup) == NULL)
615: return 1;
1.1 ratchov 616: }
1.17 ratchov 617:
618: setsig();
619: filelist_init();
620:
1.32 ratchov 621: if (!start_helper(background))
622: return 1;
623:
624: if (geteuid() == 0) {
1.20 ratchov 625: if ((pw = getpwnam(SNDIO_USER)) == NULL)
626: errx(1, "unknown user %s", SNDIO_USER);
1.32 ratchov 627: } else
628: pw = NULL;
629: getbasepath(base);
630: snprintf(path, SOCKPATH_MAX, "%s/" SOCKPATH_FILE "%u", base, unit);
631: if (!listen_new_un(path))
632: return 1;
633: for (ta = tcpaddr_list; ta != NULL; ta = ta->next) {
634: if (!listen_new_tcp(ta->host, AUCAT_PORT + unit))
635: return 1;
1.20 ratchov 636: }
1.32 ratchov 637: for (l = listen_list; l != NULL; l = l->next) {
638: if (!listen_init(l))
639: return 1;
1.13 ratchov 640: }
1.32 ratchov 641: midi_init();
642: for (p = port_list; p != NULL; p = p->next) {
643: if (!port_init(p))
644: return 1;
1.1 ratchov 645: }
1.32 ratchov 646: for (d = dev_list; d != NULL; d = d->next) {
647: if (!dev_init(d))
1.1 ratchov 648: return 1;
1.32 ratchov 649: }
650: if (background) {
651: log_flush();
652: log_level = 0;
1.35 ratchov 653: if (daemon(0, 0) == -1)
1.32 ratchov 654: err(1, "daemon");
655: }
656: if (pw != NULL) {
1.35 ratchov 657: if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) == -1)
1.32 ratchov 658: err(1, "setpriority");
1.35 ratchov 659: if (chroot(pw->pw_dir) == -1 || chdir("/") == -1)
1.32 ratchov 660: err(1, "cannot chroot to %s", pw->pw_dir);
1.35 ratchov 661: if (setgroups(1, &pw->pw_gid) == -1 ||
662: setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 ||
663: setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1 )
1.32 ratchov 664: err(1, "cannot drop privileges");
665: }
666: if (tcpaddr_list) {
667: if (pledge("stdio audio recvfd unix inet", NULL) == -1)
1.22 ratchov 668: err(1, "pledge");
1.18 ratchov 669: } else {
1.32 ratchov 670: if (pledge("stdio audio recvfd unix", NULL) == -1)
671: err(1, "pledge");
672: }
673: for (;;) {
674: if (quit_flag)
675: break;
1.36 ratchov 676: if (reopen_flag) {
677: reopen_flag = 0;
678: for (d = dev_list; d != NULL; d = d->next)
679: dev_reopen(d);
680: for (p = port_list; p != NULL; p = p->next)
681: port_reopen(p);
682: }
1.32 ratchov 683: if (!fdpass_peer)
684: break;
685: if (!file_poll())
686: break;
687: }
688: stop_helper();
689: while (listen_list != NULL)
690: listen_close(listen_list);
691: while (sock_list != NULL)
692: sock_close(sock_list);
693: for (d = dev_list; d != NULL; d = d->next)
694: dev_done(d);
695: for (p = port_list; p != NULL; p = p->next)
696: port_done(p);
697: while (file_poll())
698: ; /* nothing */
699: midi_done();
1.18 ratchov 700:
1.1 ratchov 701: while (dev_list)
702: dev_del(dev_list);
703: while (port_list)
704: port_del(port_list);
1.25 ratchov 705: while (tcpaddr_list) {
706: ta = tcpaddr_list;
707: tcpaddr_list = ta->next;
708: xfree(ta);
709: }
1.1 ratchov 710: filelist_done();
711: unsetsig();
712: return 0;
713: }