Annotation of src/usr.bin/sndiod/sndiod.c, Revision 1.45
1.45 ! ratchov 1: /* $OpenBSD: sndiod.c,v 1.44 2021/02/05 17:59:33 jcs 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.45 ! ratchov 459: int c, i, background, unit;
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: */
1.44 jcs 480: vol = 127;
1.1 ratchov 481: dup = 1;
482: mmc = 0;
483: hold = 0;
1.44 jcs 484: autovol = 0;
1.1 ratchov 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.45 ! ratchov 497: d = NULL;
! 498: p = NULL;
1.42 ratchov 499:
500: slot_array_init();
1.1 ratchov 501:
1.36 ratchov 502: while ((c = getopt(argc, argv,
503: "a:b:c:C:de:F:f:j:L:m:Q:q:r:s:t:U:v:w:x:z:")) != -1) {
1.1 ratchov 504: switch (c) {
505: case 'd':
506: log_level++;
507: background = 0;
508: break;
509: case 'U':
510: unit = strtonum(optarg, 0, 15, &str);
511: if (str)
512: errx(1, "%s: unit number is %s", optarg, str);
513: break;
514: case 'L':
1.25 ratchov 515: ta = xmalloc(sizeof(struct tcpaddr));
516: ta->host = optarg;
517: ta->next = tcpaddr_list;
518: tcpaddr_list = ta;
1.1 ratchov 519: break;
520: case 'm':
521: mode = opt_mode();
522: break;
523: case 'j':
524: dup = opt_onoff();
525: break;
526: case 't':
527: mmc = opt_mmc();
528: break;
529: case 'c':
530: opt_ch(&pmin, &pmax);
531: break;
532: case 'C':
533: opt_ch(&rmin, &rmax);
534: break;
535: case 'e':
536: opt_enc(&par);
537: break;
538: case 'r':
539: rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str);
540: if (str)
541: errx(1, "%s: rate is %s", optarg, str);
542: break;
543: case 'v':
544: vol = strtonum(optarg, 0, MIDI_MAXCTL, &str);
545: if (str)
546: errx(1, "%s: volume is %s", optarg, str);
547: break;
548: case 's':
1.45 ! ratchov 549: if (d == NULL) {
! 550: for (i = 0; default_devs[i] != NULL; i++) {
! 551: mkdev(default_devs[i], &par, 0,
! 552: bufsz, round, rate, 0, autovol);
! 553: }
! 554: d = dev_list;
1.1 ratchov 555: }
1.26 ratchov 556: if (mkopt(optarg, d, pmin, pmax, rmin, rmax,
557: mode, vol, mmc, dup) == NULL)
558: return 1;
1.1 ratchov 559: break;
560: case 'q':
1.45 ! ratchov 561: p = mkport(optarg, hold);
1.1 ratchov 562: break;
1.36 ratchov 563: case 'Q':
1.45 ! ratchov 564: if (p == NULL)
1.36 ratchov 565: errx(1, "-Q %s: no ports defined", optarg);
1.45 ! ratchov 566: namelist_add(&p->path_list, optarg);
1.36 ratchov 567: break;
1.1 ratchov 568: case 'a':
569: hold = opt_onoff();
570: break;
571: case 'w':
572: autovol = opt_onoff();
573: break;
574: case 'b':
575: bufsz = strtonum(optarg, 1, RATE_MAX, &str);
576: if (str)
577: errx(1, "%s: buffer size is %s", optarg, str);
578: break;
579: case 'z':
580: round = strtonum(optarg, 1, SHRT_MAX, &str);
581: if (str)
582: errx(1, "%s: block size is %s", optarg, str);
583: break;
584: case 'f':
1.45 ! ratchov 585: d = mkdev(optarg, &par, 0, bufsz, round,
1.28 ratchov 586: rate, hold, autovol);
1.1 ratchov 587: break;
1.36 ratchov 588: case 'F':
1.45 ! ratchov 589: if (d == NULL)
1.36 ratchov 590: errx(1, "-F %s: no devices defined", optarg);
1.41 ratchov 591: if (!dev_addname(d, optarg))
592: exit(1);
1.36 ratchov 593: break;
1.1 ratchov 594: default:
595: fputs(usagestr, stderr);
596: return 1;
597: }
598: }
599: argc -= optind;
600: argv += optind;
601: if (argc > 0) {
602: fputs(usagestr, stderr);
603: return 1;
1.39 ratchov 604: }
605: if (port_list == NULL) {
606: for (i = 0; default_ports[i] != NULL; i++)
607: mkport(default_ports[i], 0);
1.1 ratchov 608: }
1.45 ! ratchov 609: if (dev_list == NULL) {
! 610: for (i = 0; default_devs[i] != NULL; i++) {
1.40 ratchov 611: mkdev(default_devs[i], &par, 0,
612: bufsz, round, rate, 0, autovol);
613: }
614: }
1.1 ratchov 615: for (d = dev_list; d != NULL; d = d->next) {
1.33 ratchov 616: if (opt_byname(d, "default"))
1.1 ratchov 617: continue;
1.26 ratchov 618: if (mkopt("default", d, pmin, pmax, rmin, rmax,
619: mode, vol, mmc, dup) == NULL)
620: return 1;
1.1 ratchov 621: }
1.17 ratchov 622:
623: setsig();
624: filelist_init();
625:
1.32 ratchov 626: if (!start_helper(background))
627: return 1;
628:
629: if (geteuid() == 0) {
1.20 ratchov 630: if ((pw = getpwnam(SNDIO_USER)) == NULL)
631: errx(1, "unknown user %s", SNDIO_USER);
1.32 ratchov 632: } else
633: pw = NULL;
634: getbasepath(base);
635: snprintf(path, SOCKPATH_MAX, "%s/" SOCKPATH_FILE "%u", base, unit);
636: if (!listen_new_un(path))
637: return 1;
638: for (ta = tcpaddr_list; ta != NULL; ta = ta->next) {
639: if (!listen_new_tcp(ta->host, AUCAT_PORT + unit))
640: return 1;
1.20 ratchov 641: }
1.32 ratchov 642: for (l = listen_list; l != NULL; l = l->next) {
643: if (!listen_init(l))
644: return 1;
1.13 ratchov 645: }
1.32 ratchov 646: midi_init();
647: for (p = port_list; p != NULL; p = p->next) {
648: if (!port_init(p))
649: return 1;
1.1 ratchov 650: }
1.32 ratchov 651: for (d = dev_list; d != NULL; d = d->next) {
652: if (!dev_init(d))
1.1 ratchov 653: return 1;
1.32 ratchov 654: }
655: if (background) {
656: log_flush();
657: log_level = 0;
1.35 ratchov 658: if (daemon(0, 0) == -1)
1.32 ratchov 659: err(1, "daemon");
660: }
661: if (pw != NULL) {
1.35 ratchov 662: if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) == -1)
1.32 ratchov 663: err(1, "setpriority");
1.35 ratchov 664: if (chroot(pw->pw_dir) == -1 || chdir("/") == -1)
1.32 ratchov 665: err(1, "cannot chroot to %s", pw->pw_dir);
1.35 ratchov 666: if (setgroups(1, &pw->pw_gid) == -1 ||
667: setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 ||
668: setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1 )
1.32 ratchov 669: err(1, "cannot drop privileges");
670: }
671: if (tcpaddr_list) {
672: if (pledge("stdio audio recvfd unix inet", NULL) == -1)
1.22 ratchov 673: err(1, "pledge");
1.18 ratchov 674: } else {
1.32 ratchov 675: if (pledge("stdio audio recvfd unix", NULL) == -1)
676: err(1, "pledge");
677: }
678: for (;;) {
679: if (quit_flag)
680: break;
1.36 ratchov 681: if (reopen_flag) {
682: reopen_flag = 0;
683: for (d = dev_list; d != NULL; d = d->next)
684: dev_reopen(d);
685: for (p = port_list; p != NULL; p = p->next)
686: port_reopen(p);
687: }
1.32 ratchov 688: if (!fdpass_peer)
689: break;
690: if (!file_poll())
691: break;
692: }
693: stop_helper();
694: while (listen_list != NULL)
695: listen_close(listen_list);
696: while (sock_list != NULL)
697: sock_close(sock_list);
698: for (d = dev_list; d != NULL; d = d->next)
699: dev_done(d);
700: for (p = port_list; p != NULL; p = p->next)
701: port_done(p);
702: while (file_poll())
703: ; /* nothing */
704: midi_done();
1.18 ratchov 705:
1.43 ratchov 706: while (opt_list)
707: opt_del(opt_list);
1.1 ratchov 708: while (dev_list)
709: dev_del(dev_list);
710: while (port_list)
711: port_del(port_list);
1.25 ratchov 712: while (tcpaddr_list) {
713: ta = tcpaddr_list;
714: tcpaddr_list = ta->next;
715: xfree(ta);
716: }
1.1 ratchov 717: filelist_done();
718: unsetsig();
719: return 0;
720: }