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

Annotation of src/usr.bin/aucat/aucat.c, Revision 1.136

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