[BACK]Return to sndiod.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sndiod

Annotation of src/usr.bin/sndiod/sndiod.c, Revision 1.38

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