[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.121

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