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

1.117   ! ratchov     1: /*     $OpenBSD: aucat.c,v 1.116 2011/06/03 10:05:27 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.78      ratchov    68: #ifdef DEBUG
1.111     deraadt    69: volatile sig_atomic_t debug_level = 0;
1.78      ratchov    70: #endif
1.111     deraadt    71: volatile sig_atomic_t quit_flag = 0;
1.7       deraadt    72:
1.28      ratchov    73: /*
                     74:  * SIGINT handler, it raises the quit flag. If the flag is already set,
                     75:  * that means that the last SIGINT was not handled, because the process
1.62      ratchov    76:  * is blocked somewhere, so exit.
1.28      ratchov    77:  */
                     78: void
                     79: sigint(int s)
                     80: {
                     81:        if (quit_flag)
                     82:                _exit(1);
                     83:        quit_flag = 1;
                     84: }
1.22      ratchov    85:
1.78      ratchov    86: #ifdef DEBUG
                     87: /*
                     88:  * Increase debug level on SIGUSR1.
                     89:  */
                     90: void
                     91: sigusr1(int s)
                     92: {
                     93:        if (debug_level < 4)
                     94:                debug_level++;
                     95: }
                     96:
                     97: /*
                     98:  * Decrease debug level on SIGUSR2.
                     99:  */
                    100: void
                    101: sigusr2(int s)
                    102: {
                    103:        if (debug_level > 0)
                    104:                debug_level--;
                    105: }
                    106: #endif
1.15      ratchov   107:
                    108: void
                    109: opt_ch(struct aparams *par)
                    110: {
1.76      ratchov   111:        char *next, *end;
                    112:        long cmin, cmax;
1.13      uwe       113:
1.76      ratchov   114:        errno = 0;
                    115:        cmin = strtol(optarg, &next, 10);
                    116:        if (next == optarg || *next != ':')
                    117:                goto failed;
                    118:        cmax = strtol(++next, &end, 10);
                    119:        if (end == next || *end != '\0')
                    120:                goto failed;
                    121:        if (cmin < 0 || cmax < cmin || cmax > NCHAN_MAX)
                    122:                goto failed;
                    123:        par->cmin = cmin;
                    124:        par->cmax = cmax;
                    125:        return;
                    126: failed:
                    127:        errx(1, "%s: bad channel range", optarg);
1.15      ratchov   128: }
1.13      uwe       129:
1.15      ratchov   130: void
                    131: opt_enc(struct aparams *par)
                    132: {
1.28      ratchov   133:        int len;
                    134:
                    135:        len = aparams_strtoenc(par, optarg);
                    136:        if (len == 0 || optarg[len] != '\0')
                    137:                errx(1, "%s: bad encoding", optarg);
1.15      ratchov   138: }
1.4       millert   139:
1.15      ratchov   140: int
                    141: opt_hdr(void)
                    142: {
                    143:        if (strcmp("auto", optarg) == 0)
                    144:                return HDR_AUTO;
                    145:        if (strcmp("raw", optarg) == 0)
                    146:                return HDR_RAW;
                    147:        if (strcmp("wav", optarg) == 0)
                    148:                return HDR_WAV;
1.35      ratchov   149:        errx(1, "%s: bad header specification", optarg);
1.1       kstailey  150: }
                    151:
1.22      ratchov   152: int
1.74      ratchov   153: opt_mmc(void)
                    154: {
                    155:        if (strcmp("off", optarg) == 0)
                    156:                return 0;
                    157:        if (strcmp("slave", optarg) == 0)
                    158:                return 1;
                    159:        errx(1, "%s: bad MMC mode", optarg);
                    160: }
                    161:
                    162: int
1.90      ratchov   163: opt_onoff(void)
1.84      ratchov   164: {
                    165:        if (strcmp("off", optarg) == 0)
                    166:                return 0;
                    167:        if (strcmp("on", optarg) == 0)
                    168:                return 1;
                    169:        errx(1, "%s: bad join/expand setting", optarg);
                    170: }
                    171:
                    172: int
1.22      ratchov   173: opt_xrun(void)
                    174: {
                    175:        if (strcmp("ignore", optarg) == 0)
                    176:                return XRUN_IGNORE;
                    177:        if (strcmp("sync", optarg) == 0)
                    178:                return XRUN_SYNC;
                    179:        if (strcmp("error", optarg) == 0)
                    180:                return XRUN_ERROR;
1.73      ratchov   181:        errx(1, "%s: bad underrun/overrun policy", optarg);
1.22      ratchov   182: }
                    183:
1.83      ratchov   184: unsigned
1.43      ratchov   185: opt_mode(void)
                    186: {
1.83      ratchov   187:        unsigned mode = 0;
                    188:        char *p = optarg;
                    189:        size_t len;
                    190:
1.104     ratchov   191:        for (p = optarg; *p != '\0'; p++) {
1.83      ratchov   192:                len = strcspn(p, ",");
                    193:                if (strncmp("play", p, len) == 0) {
                    194:                        mode |= MODE_PLAY;
                    195:                } else if (strncmp("rec", p, len) == 0) {
                    196:                        mode |= MODE_REC;
                    197:                } else if (strncmp("mon", p, len) == 0) {
                    198:                        mode |= MODE_MON;
                    199:                } else if (strncmp("duplex", p, len) == 0) {
                    200:                        /* XXX: backward compat, remove this */
                    201:                        mode |= MODE_REC | MODE_PLAY;
                    202:                } else
                    203:                        errx(1, "%s: bad mode", optarg);
                    204:                p += len;
                    205:                if (*p == '\0')
                    206:                        break;
                    207:        }
                    208:        if (mode == 0)
                    209:                errx(1, "empty mode");
                    210:        return mode;
1.43      ratchov   211: }
                    212:
1.13      uwe       213: /*
1.92      ratchov   214:  * stream configuration
                    215:  */
                    216: struct cfstr {
                    217:        SLIST_ENTRY(cfstr) entry;
                    218:        unsigned mode;                  /* bitmap of MODE_XXX */
                    219:        struct aparams ipar;            /* input (read) parameters */
                    220:        struct aparams opar;            /* output (write) parameters */
                    221:        unsigned vol;                   /* last requested volume */
                    222:        int hdr;                        /* header format */
                    223:        int xrun;                       /* overrun/underrun policy */
                    224:        int mmc;                        /* MMC mode */
                    225:        int join;                       /* join/expand enabled */
                    226:        char *path;                     /* static path (no need to copy it) */
                    227: };
                    228:
                    229: SLIST_HEAD(cfstrlist, cfstr);
                    230:
                    231: /*
                    232:  * midi device (control stream)
1.13      uwe       233:  */
1.92      ratchov   234: struct cfmid {
                    235:        SLIST_ENTRY(cfmid) entry;
                    236:        char *path;                     /* static path (no need to copy it) */
1.15      ratchov   237: };
1.13      uwe       238:
1.92      ratchov   239: SLIST_HEAD(cfmidlist, cfmid);
1.13      uwe       240:
1.15      ratchov   241: /*
1.92      ratchov   242:  * audio device configuration
1.15      ratchov   243:  */
1.92      ratchov   244: struct cfdev {
                    245:        SLIST_ENTRY(cfdev) entry;
                    246:        struct cfstrlist ins;           /* files to play */
                    247:        struct cfstrlist outs;          /* files to record */
                    248:        struct cfstrlist opts;          /* subdevices to expose */
                    249:        struct cfmidlist mids;          /* midi ports to subscribe */
                    250:        struct aparams ipar;            /* input (read) parameters */
                    251:        struct aparams opar;            /* output (write) parameters */
1.93      ratchov   252:        unsigned hold;                  /* open immediately */
1.115     ratchov   253:        unsigned autovol;               /* adjust volumes */
1.92      ratchov   254:        unsigned bufsz;                 /* par.bufsz for sio device */
                    255:        unsigned round;                 /* par.round for sio device */
                    256:        unsigned mode;                  /* bitmap of MODE_XXX */
                    257:        char *path;                     /* static path (no need to copy it) */
                    258: };
                    259:
                    260: SLIST_HEAD(cfdevlist, cfdev);
                    261:
1.113     ratchov   262: /*
                    263:  * local network addresse to listen on
                    264:  */
                    265: struct cfnet {
                    266:        SLIST_ENTRY(cfnet) entry;
                    267:        char *addr;
                    268: };
                    269:
                    270: SLIST_HEAD(cfnetlist, cfnet);
                    271:
1.116     ratchov   272: struct cfdev *
                    273: cfdev_new(struct cfdev *templ)
1.92      ratchov   274: {
                    275:        struct cfdev *cd;
                    276:
                    277:        cd = malloc(sizeof(struct cfdev));
                    278:        if (cd == NULL) {
                    279:                perror("malloc");
                    280:                abort();
                    281:        }
1.116     ratchov   282:        if (templ)
                    283:                memcpy(cd, templ, sizeof(struct cfdev));
                    284:        else {
                    285:                aparams_init(&cd->ipar, 0, 1, DEFAULT_RATE);
                    286:                aparams_init(&cd->opar, 0, 1, DEFAULT_RATE);
                    287:                cd->bufsz = 0;
                    288:                cd->round = 0;
                    289:                cd->hold = 1;
                    290:                cd->autovol = 1;
                    291:        }
                    292:        SLIST_INIT(&cd->ins);
                    293:        SLIST_INIT(&cd->outs);
                    294:        SLIST_INIT(&cd->opts);
                    295:        SLIST_INIT(&cd->mids);
                    296:        cd->path = NULL;
                    297:        return cd;
                    298: }
                    299:
                    300: void
                    301: cfdev_add(struct cfdevlist *list, struct cfdev *cd, char *path)
                    302: {
1.92      ratchov   303:        cd->path = path;
                    304:        SLIST_INSERT_HEAD(list, cd, entry);
                    305: }
                    306:
1.116     ratchov   307: struct cfstr *
                    308: cfstr_new(struct cfstr *templ)
1.92      ratchov   309: {
                    310:        struct cfstr *cs;
                    311:
                    312:        cs = malloc(sizeof(struct cfstr));
                    313:        if (cs == NULL) {
                    314:                perror("malloc");
                    315:                abort();
                    316:        }
1.116     ratchov   317:        if (templ)
                    318:                memcpy(cs, templ, sizeof(struct cfstr));
                    319:        else {
                    320:                aparams_init(&cs->ipar, 0, 1, DEFAULT_RATE);
                    321:                aparams_init(&cs->opar, 0, 1, DEFAULT_RATE);
                    322:                cs->mmc = 0;
                    323:                cs->hdr = HDR_AUTO;
                    324:                cs->xrun = XRUN_IGNORE;
                    325:                cs->vol = MIDI_MAXCTL;
                    326:                cs->mode = MODE_PLAY | MODE_REC;
                    327:                cs->join = 1;
                    328:        }
                    329:        cs->path = NULL;
                    330:        return cs;
                    331: }
                    332:
                    333: void
                    334: cfstr_add(struct cfstrlist *list, struct cfstr *cs, char *path)
                    335: {
1.92      ratchov   336:        cs->path = path;
                    337:        SLIST_INSERT_HEAD(list, cs, entry);
                    338: }
                    339:
                    340: void
                    341: cfmid_add(struct cfmidlist *list, char *path)
                    342: {
                    343:        struct cfmid *cm;
                    344:
                    345:        cm = malloc(sizeof(struct cfmid));
                    346:        if (cm == NULL) {
                    347:                perror("malloc");
                    348:                abort();
                    349:        }
                    350:        cm->path = path;
                    351:        SLIST_INSERT_HEAD(list, cm, entry);
1.15      ratchov   352: }
1.13      uwe       353:
1.61      ratchov   354: void
1.113     ratchov   355: cfnet_add(struct cfnetlist *list, char *addr)
                    356: {
                    357:        struct cfnet *cn;
                    358:
                    359:        cn = malloc(sizeof(struct cfnet));
                    360:        if (cn == NULL) {
                    361:                perror("malloc");
                    362:                abort();
                    363:        }
                    364:        cn->addr = addr;
                    365:        SLIST_INSERT_HEAD(list, cn, entry);
                    366: }
                    367:
                    368: void
1.61      ratchov   369: setsig(void)
                    370: {
                    371:        struct sigaction sa;
                    372:
                    373:        quit_flag = 0;
                    374:        sigfillset(&sa.sa_mask);
                    375:        sa.sa_flags = SA_RESTART;
                    376:        sa.sa_handler = sigint;
                    377:        if (sigaction(SIGINT, &sa, NULL) < 0)
1.68      ratchov   378:                err(1, "sigaction(int) failed");
1.61      ratchov   379:        if (sigaction(SIGTERM, &sa, NULL) < 0)
1.68      ratchov   380:                err(1, "sigaction(term) failed");
1.61      ratchov   381:        if (sigaction(SIGHUP, &sa, NULL) < 0)
1.68      ratchov   382:                err(1, "sigaction(hup) failed");
1.78      ratchov   383: #ifdef DEBUG
                    384:        sa.sa_handler = sigusr1;
                    385:        if (sigaction(SIGUSR1, &sa, NULL) < 0)
                    386:                err(1, "sigaction(usr1) failed");
                    387:        sa.sa_handler = sigusr2;
                    388:        if (sigaction(SIGUSR2, &sa, NULL) < 0)
                    389:                err(1, "sigaction(usr2) failed1n");
                    390: #endif
1.61      ratchov   391: }
                    392:
                    393: void
                    394: unsetsig(void)
                    395: {
                    396:        struct sigaction sa;
                    397:
                    398:        sigfillset(&sa.sa_mask);
                    399:        sa.sa_flags = SA_RESTART;
                    400:        sa.sa_handler = SIG_DFL;
1.78      ratchov   401: #ifdef DEBUG
                    402:        if (sigaction(SIGUSR2, &sa, NULL) < 0)
                    403:                err(1, "unsetsig(usr2): sigaction failed");
                    404:        if (sigaction(SIGUSR1, &sa, NULL) < 0)
                    405:                err(1, "unsetsig(usr1): sigaction failed");
                    406: #endif
1.61      ratchov   407:        if (sigaction(SIGHUP, &sa, NULL) < 0)
1.68      ratchov   408:                err(1, "unsetsig(hup): sigaction failed\n");
1.61      ratchov   409:        if (sigaction(SIGTERM, &sa, NULL) < 0)
1.68      ratchov   410:                err(1, "unsetsig(term): sigaction failed\n");
1.61      ratchov   411:        if (sigaction(SIGINT, &sa, NULL) < 0)
1.68      ratchov   412:                err(1, "unsetsig(int): sigaction failed\n");
1.61      ratchov   413: }
                    414:
                    415: void
                    416: getbasepath(char *base, size_t size)
                    417: {
                    418:        uid_t uid;
                    419:        struct stat sb;
1.86      ratchov   420:        mode_t mask;
1.61      ratchov   421:
                    422:        uid = geteuid();
1.86      ratchov   423:        if (uid == 0) {
                    424:                mask = 022;
                    425:                snprintf(base, PATH_MAX, "/tmp/aucat");
                    426:        } else {
                    427:                mask = 077;
                    428:                snprintf(base, PATH_MAX, "/tmp/aucat-%u", uid);
                    429:        }
                    430:        if (mkdir(base, 0777 & ~mask) < 0) {
1.61      ratchov   431:                if (errno != EEXIST)
                    432:                        err(1, "mkdir(\"%s\")", base);
                    433:        }
                    434:        if (stat(base, &sb) < 0)
                    435:                err(1, "stat(\"%s\")", base);
1.86      ratchov   436:        if (sb.st_uid != uid || (sb.st_mode & mask) != 0)
1.61      ratchov   437:                errx(1, "%s has wrong permissions", base);
                    438: }
                    439:
                    440: void
1.86      ratchov   441: privdrop(void)
                    442: {
                    443:        struct passwd *pw;
                    444:        struct stat sb;
                    445:
                    446:        if ((pw = getpwnam(SNDIO_USER)) == NULL)
1.105     deraadt   447:                errx(1, "unknown user %s", SNDIO_USER);
1.86      ratchov   448:        if (stat(pw->pw_dir, &sb) < 0)
                    449:                err(1, "stat(\"%s\")", pw->pw_dir);
                    450:        if (sb.st_uid != 0 || (sb.st_mode & 022) != 0)
                    451:                errx(1, "%s has wrong permissions", pw->pw_dir);
                    452:        if (setpriority(PRIO_PROCESS, 0, SNDIO_PRIO) < 0)
                    453:                err(1, "setpriority");
                    454:        if (setgroups(1, &pw->pw_gid) ||
                    455:            setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
                    456:            setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
                    457:                err(1, "cannot drop privileges");
                    458: }
                    459:
                    460: void
1.61      ratchov   461: aucat_usage(void)
                    462: {
1.92      ratchov   463:        (void)fputs("usage: " PROG_AUCAT " [-dlnu] [-a flag] [-b nframes] "
1.83      ratchov   464:            "[-C min:max] [-c min:max] [-e enc]\n\t"
1.113     ratchov   465:            "[-f device] [-h fmt] [-i file] [-j flag] [-L addr] [-m mode] "
                    466:            "[-o file]\n\t"
                    467:            "[-q device] [-r rate] [-s name] [-t mode] [-U unit] "
                    468:            "[-v volume]\n\t"
1.115     ratchov   469:            "[-w flag] [-x policy] [-z nframes]\n",
1.61      ratchov   470:            stderr);
                    471: }
                    472:
1.1       kstailey  473: int
1.61      ratchov   474: aucat_main(int argc, char **argv)
1.1       kstailey  475: {
1.92      ratchov   476:        struct cfdevlist cfdevs;
1.113     ratchov   477:        struct cfnetlist cfnets;
1.92      ratchov   478:        struct cfmid *cm;
                    479:        struct cfstr *cs;
                    480:        struct cfdev *cd;
1.113     ratchov   481:        struct cfnet *cn;
1.92      ratchov   482:        int c, u_flag, d_flag, l_flag, n_flag, unit;
                    483:        char base[PATH_MAX], path[PATH_MAX];
                    484:        unsigned mode, rate;
1.76      ratchov   485:        const char *str;
1.102     ratchov   486:        int autostart;
1.92      ratchov   487:        struct dev *d, *dnext;
                    488:        unsigned active;
1.116     ratchov   489:        unsigned nsock;
1.19      ratchov   490:
1.92      ratchov   491:        /*
                    492:         * global options defaults
                    493:         */
                    494:        unit = -1;
1.26      ratchov   495:        u_flag = 0;
1.69      ratchov   496:        d_flag = 0;
1.28      ratchov   497:        l_flag = 0;
1.51      ratchov   498:        n_flag = 0;
1.92      ratchov   499:        SLIST_INIT(&cfdevs);
1.113     ratchov   500:        SLIST_INIT(&cfnets);
1.116     ratchov   501:        nsock = 0;
1.92      ratchov   502:
                    503:        /*
1.116     ratchov   504:         * default device and stream
1.92      ratchov   505:         */
1.116     ratchov   506:        cd = cfdev_new(NULL);
                    507:        cs = cfstr_new(NULL);
1.15      ratchov   508:
1.115     ratchov   509:        while ((c = getopt(argc, argv, "a:w:dnb:c:C:e:r:h:x:v:i:o:f:m:luq:s:U:L:t:j:z:")) != -1) {
1.15      ratchov   510:                switch (c) {
1.69      ratchov   511:                case 'd':
1.78      ratchov   512: #ifdef DEBUG
                    513:                        if (d_flag)
                    514:                                debug_level++;
                    515: #endif
1.69      ratchov   516:                        d_flag = 1;
                    517:                        break;
1.51      ratchov   518:                case 'n':
                    519:                        n_flag = 1;
                    520:                        break;
1.92      ratchov   521:                case 'u':
                    522:                        u_flag = 1;
                    523:                        break;
                    524:                case 'U':
                    525:                        unit = strtonum(optarg, 0, MIDI_MAXCTL, &str);
                    526:                        if (str)
                    527:                                errx(1, "%s: unit number is %s", optarg, str);
                    528:                        break;
1.113     ratchov   529:                case 'L':
                    530:                        cfnet_add(&cfnets, optarg);
                    531:                        break;
1.43      ratchov   532:                case 'm':
1.92      ratchov   533:                        cs->mode = opt_mode();
1.43      ratchov   534:                        break;
1.15      ratchov   535:                case 'h':
1.92      ratchov   536:                        cs->hdr = opt_hdr();
1.15      ratchov   537:                        break;
1.22      ratchov   538:                case 'x':
1.92      ratchov   539:                        cs->xrun = opt_xrun();
1.22      ratchov   540:                        break;
1.84      ratchov   541:                case 'j':
1.92      ratchov   542:                        cs->join = opt_onoff();
1.84      ratchov   543:                        break;
1.74      ratchov   544:                case 't':
1.92      ratchov   545:                        cs->mmc = opt_mmc();
1.74      ratchov   546:                        break;
1.15      ratchov   547:                case 'c':
1.92      ratchov   548:                        opt_ch(&cs->ipar);
                    549:                        cd->opar.cmin = cs->ipar.cmin;
                    550:                        cd->opar.cmax = cs->ipar.cmax;
1.15      ratchov   551:                        break;
                    552:                case 'C':
1.92      ratchov   553:                        opt_ch(&cs->opar);
                    554:                        cd->ipar.cmin = cs->opar.cmin;
                    555:                        cd->ipar.cmax = cs->opar.cmax;
1.15      ratchov   556:                        break;
                    557:                case 'e':
1.92      ratchov   558:                        opt_enc(&cs->ipar);
                    559:                        aparams_copyenc(&cs->opar, &cs->ipar);
1.117   ! ratchov   560:                        aparams_copyenc(&cd->ipar, &cs->ipar);
        !           561:                        aparams_copyenc(&cd->opar, &cd->ipar);
1.15      ratchov   562:                        break;
                    563:                case 'r':
1.92      ratchov   564:                        rate = strtonum(optarg, RATE_MIN, RATE_MAX, &str);
1.76      ratchov   565:                        if (str)
                    566:                                errx(1, "%s: rate is %s", optarg, str);
1.92      ratchov   567:                        cs->opar.rate = cs->ipar.rate = rate;
                    568:                        cd->ipar.rate = cd->opar.rate = rate;
1.15      ratchov   569:                        break;
1.35      ratchov   570:                case 'v':
1.92      ratchov   571:                        cs->vol = strtonum(optarg, 0, MIDI_MAXCTL, &str);
1.76      ratchov   572:                        if (str)
                    573:                                errx(1, "%s: volume is %s", optarg, str);
1.35      ratchov   574:                        break;
1.15      ratchov   575:                case 'i':
1.92      ratchov   576:                        cfstr_add(&cd->ins, cs, optarg);
1.116     ratchov   577:                        cs = cfstr_new(cs);
1.15      ratchov   578:                        break;
                    579:                case 'o':
1.92      ratchov   580:                        cfstr_add(&cd->outs, cs, optarg);
1.116     ratchov   581:                        cs = cfstr_new(cs);
1.42      ratchov   582:                        break;
                    583:                case 's':
1.92      ratchov   584:                        cfstr_add(&cd->opts, cs, optarg);
1.116     ratchov   585:                        cs = cfstr_new(cs);
1.98      ratchov   586:                        nsock++;
1.92      ratchov   587:                        break;
                    588:                case 'a':
                    589:                        cd->hold = opt_onoff();
1.83      ratchov   590:                        break;
1.115     ratchov   591:                case 'w':
                    592:                        cd->autovol = opt_onoff();
                    593:                        break;
1.83      ratchov   594:                case 'q':
1.92      ratchov   595:                        cfmid_add(&cd->mids, optarg);
1.4       millert   596:                        break;
1.28      ratchov   597:                case 'b':
1.92      ratchov   598:                        cd->bufsz = strtonum(optarg, 1, RATE_MAX * 5, &str);
1.76      ratchov   599:                        if (str)
                    600:                                errx(1, "%s: buffer size is %s", optarg, str);
1.28      ratchov   601:                        break;
1.74      ratchov   602:                case 'z':
1.92      ratchov   603:                        cd->round = strtonum(optarg, 1, SHRT_MAX, &str);
1.76      ratchov   604:                        if (str)
                    605:                                errx(1, "%s: block size is %s", optarg, str);
1.74      ratchov   606:                        break;
1.92      ratchov   607:                case 'f':
1.98      ratchov   608:                        if (SLIST_EMPTY(&cd->opts) &&
                    609:                            SLIST_EMPTY(&cd->ins) &&
                    610:                            SLIST_EMPTY(&cd->outs)) {
                    611:                                cfstr_add(&cd->opts, cs, DEFAULT_OPT);
1.116     ratchov   612:                                cs = cfstr_new(cs);
1.98      ratchov   613:                                nsock++;
                    614:                        }
1.92      ratchov   615:                        cfdev_add(&cfdevs, cd, optarg);
1.116     ratchov   616:                        cd = cfdev_new(cd);
1.92      ratchov   617:                        break;
                    618:                case 'l':
                    619:                        l_flag = 1;
                    620:                        autostart = 0;
                    621:                        break;
1.11      jaredy    622:                default:
1.61      ratchov   623:                        aucat_usage();
1.15      ratchov   624:                        exit(1);
1.4       millert   625:                }
                    626:        }
                    627:        argc -= optind;
                    628:        argv += optind;
                    629:
1.92      ratchov   630: #ifdef DEBUG
                    631:        if (debug_level == 0)
                    632:                debug_level = 1;
                    633: #endif
                    634:        if (argc > 0) {
1.102     ratchov   635:                aucat_usage();
                    636:                exit(1);
1.15      ratchov   637:        }
                    638:
1.98      ratchov   639:        /*
                    640:         * Check constraints specific to -n option
                    641:         */
1.51      ratchov   642:        if (n_flag) {
1.98      ratchov   643:                if (!SLIST_EMPTY(&cfdevs) ||
                    644:                    !SLIST_EMPTY(&cd->mids) ||
                    645:                    !SLIST_EMPTY(&cd->opts))
                    646:                        errx(1, "-f, -s, and -q not allowed in loopback mode");
1.92      ratchov   647:                if (SLIST_EMPTY(&cd->ins) || SLIST_EMPTY(&cd->outs))
1.98      ratchov   648:                        errx(1, "-i and -o are required in loopback mode");
1.51      ratchov   649:        }
1.15      ratchov   650:
1.46      ratchov   651:        /*
1.98      ratchov   652:         * If there's no device specified, do as if the default
                    653:         * device is specified as last argument.
1.92      ratchov   654:         */
                    655:        if (SLIST_EMPTY(&cfdevs)) {
1.98      ratchov   656:                if (SLIST_EMPTY(&cd->opts) &&
                    657:                    SLIST_EMPTY(&cd->ins) &&
                    658:                    SLIST_EMPTY(&cd->outs)) {
                    659:                        cfstr_add(&cd->opts, cs, DEFAULT_OPT);
                    660:                        nsock++;
1.116     ratchov   661:                } else
                    662:                        free(cs);
1.92      ratchov   663:                if (!cd->hold)
1.98      ratchov   664:                        errx(1, "-a off not compatible with default device");
1.92      ratchov   665:                cfdev_add(&cfdevs, cd, "default");
1.116     ratchov   666:        } else {
                    667:                if (!SLIST_EMPTY(&cd->opts) ||
                    668:                    !SLIST_EMPTY(&cd->ins) ||
                    669:                    !SLIST_EMPTY(&cd->outs) ||
                    670:                    !SLIST_EMPTY(&cd->outs))
                    671:                        errx(1, "no device to attach last stream to");
                    672:                free(cs);
                    673:                free(cd);
1.92      ratchov   674:        }
1.46      ratchov   675:
1.83      ratchov   676:        /*
                    677:         * Check modes and calculate "best" device parameters. Iterate over all
                    678:         * inputs and outputs and find the maximum sample rate and channel
                    679:         * number.
                    680:         */
1.92      ratchov   681:        SLIST_FOREACH(cd, &cfdevs, entry) {
                    682:                mode = 0;
1.117   ! ratchov   683:                if (!u_flag) {
        !           684:                        aparams_init(&cd->opar, NCHAN_MAX - 1, 0, RATE_MIN);
        !           685:                        aparams_init(&cd->opar, NCHAN_MAX - 1, 0, RATE_MIN);
        !           686:                }
1.92      ratchov   687:                SLIST_FOREACH(cs, &cd->ins, entry) {
                    688:                        if (cs->mode == 0)
                    689:                                errx(1, "%s: not in play mode", cs->path);
                    690:                        mode |= (cs->mode & MODE_PLAY);
                    691:                        if (!u_flag)
                    692:                                aparams_grow(&cd->opar, &cs->ipar);
                    693:                }
                    694:                SLIST_FOREACH(cs, &cd->outs, entry) {
                    695:                        if (cs->mode == 0)
                    696:                                errx(1, "%s: not in rec/mon mode", cs->path);
                    697:                        if ((cs->mode & MODE_REC) && (cs->mode & MODE_MON))
                    698:                                errx(1, "%s: can't rec and mon", cs->path);
                    699:                        mode |= (cs->mode & MODE_RECMASK);
                    700:                        if (!u_flag)
                    701:                                aparams_grow(&cd->ipar, &cs->opar);
                    702:                }
                    703:                SLIST_FOREACH(cs, &cd->opts, entry) {
                    704:                        if ((cs->mode & MODE_REC) && (cs->mode & MODE_MON))
                    705:                                errx(1, "%s: can't rec and mon", cs->path);
                    706:                        mode |= (cs->mode & (MODE_RECMASK | MODE_PLAY));
                    707:                        if (!u_flag) {
                    708:                                aparams_grow(&cd->opar, &cs->ipar);
                    709:                                aparams_grow(&cd->ipar, &cs->opar);
                    710:                        }
                    711:                }
                    712:                if ((mode & MODE_MON) && !(mode & MODE_PLAY))
                    713:                        errx(1, "no playback stream to monitor");
1.98      ratchov   714:                if (n_flag && (mode & MODE_MON))
                    715:                        errx(1, "-m mon not allowed in loopback mode");
1.92      ratchov   716:                rate = (mode & MODE_REC) ? cd->ipar.rate : cd->opar.rate;
                    717:                if (!cd->round)
                    718:                        cd->round = rate / 15;
                    719:                if (!cd->bufsz)
                    720:                        cd->bufsz = rate / 15 * 4;
                    721:                cd->mode = mode;
1.42      ratchov   722:        }
1.98      ratchov   723:        if (nsock > 0) {
1.61      ratchov   724:                getbasepath(base, sizeof(base));
                    725:                if (unit < 0)
                    726:                        unit = 0;
1.55      ratchov   727:        }
1.61      ratchov   728:        setsig();
1.28      ratchov   729:        filelist_init();
1.51      ratchov   730:
1.15      ratchov   731:        /*
1.92      ratchov   732:         * Open devices
1.15      ratchov   733:         */
1.92      ratchov   734:        while (!SLIST_EMPTY(&cfdevs)) {
                    735:                cd = SLIST_FIRST(&cfdevs);
                    736:                SLIST_REMOVE_HEAD(&cfdevs, entry);
                    737:
                    738:                if (n_flag) {
                    739:                        d = dev_new_loop(&cd->ipar, &cd->opar, cd->bufsz);
                    740:                } else {
1.106     ratchov   741:                        d = dev_new_sio(cd->path, cd->mode | MODE_MIDIMASK,
1.92      ratchov   742:                            &cd->ipar, &cd->opar, cd->bufsz, cd->round,
1.115     ratchov   743:                            cd->hold, cd->autovol);
1.92      ratchov   744:                }
                    745:                if (d == NULL)
                    746:                        errx(1, "%s: can't open device", cd->path);
                    747:
                    748:                /*
                    749:                 * register midi devices
                    750:                 */
                    751:                while (!SLIST_EMPTY(&cd->mids)) {
                    752:                        cm = SLIST_FIRST(&cd->mids);
                    753:                        SLIST_REMOVE_HEAD(&cd->mids, entry);
                    754:                        if (!dev_thruadd(d, cm->path, 1, 1))
                    755:                                errx(1, "%s: can't open device", cm->path);
                    756:                        free(cm);
                    757:                }
1.52      ratchov   758:
1.92      ratchov   759:                /*
                    760:                 * register files
                    761:                 */
                    762:                autostart = 0;
                    763:                while (!SLIST_EMPTY(&cd->ins)) {
                    764:                        cs = SLIST_FIRST(&cd->ins);
                    765:                        SLIST_REMOVE_HEAD(&cd->ins, entry);
                    766:                        if (!cs->mmc)
                    767:                                autostart = 1;
1.103     ratchov   768:                        if (strcmp(cs->path, "-") == 0)
                    769:                                cs->path = NULL;
1.92      ratchov   770:                        if (!wav_new_in(&wav_ops, d, cs->mode & MODE_PLAY,
                    771:                                cs->path, cs->hdr, &cs->ipar, cs->xrun,
                    772:                                cs->vol, cs->mmc, cs->join))
                    773:                                exit(1);
                    774:                        free(cs);
                    775:                }
                    776:                while (!SLIST_EMPTY(&cd->outs)) {
                    777:                        cs = SLIST_FIRST(&cd->outs);
                    778:                        SLIST_REMOVE_HEAD(&cd->outs, entry);
                    779:                        if (!cs->mmc)
                    780:                                autostart = 1;
1.103     ratchov   781:                        if (strcmp(cs->path, "-") == 0)
                    782:                                cs->path = NULL;
1.92      ratchov   783:                        if (!wav_new_out(&wav_ops, d, cs->mode & MODE_RECMASK,
                    784:                                cs->path, cs->hdr, &cs->opar, cs->xrun,
                    785:                                cs->mmc, cs->join))
                    786:                                exit(1);
                    787:                        free(cs);
                    788:                }
                    789:                while (!SLIST_EMPTY(&cd->opts)) {
                    790:                        cs = SLIST_FIRST(&cd->opts);
                    791:                        SLIST_REMOVE_HEAD(&cd->opts, entry);
                    792:                        opt_new(cs->path, d, &cs->opar, &cs->ipar,
                    793:                            MIDI_TO_ADATA(cs->vol), cs->mmc,
1.106     ratchov   794:                            cs->join, cs->mode | MODE_MIDIMASK);
1.92      ratchov   795:                        free(cs);
                    796:                }
                    797:                free(cd);
                    798:                if (autostart) {
                    799:                        /*
                    800:                         * inject artificial mmc start
                    801:                         */
                    802:                        ctl_start(d->midi);
                    803:                }
1.56      ratchov   804:        }
1.98      ratchov   805:        if (nsock > 0) {
1.61      ratchov   806:                snprintf(path, sizeof(path), "%s/%s%u", base,
1.109     ratchov   807:                    AUCAT_PATH, unit);
1.110     ratchov   808:                listen_new_un(path);
1.113     ratchov   809:                while (!SLIST_EMPTY(&cfnets)) {
                    810:                        cn = SLIST_FIRST(&cfnets);
                    811:                        SLIST_REMOVE_HEAD(&cfnets, entry);
                    812:                        listen_new_tcp(cn->addr, AUCAT_PORT + unit);
                    813:                }
1.98      ratchov   814:        }
                    815:        if (geteuid() == 0)
                    816:                privdrop();
                    817:        if (l_flag) {
1.107     ratchov   818: #ifdef DEBUG
1.98      ratchov   819:                debug_level = 0;
                    820:                dbg_flush();
1.107     ratchov   821: #endif
1.98      ratchov   822:                if (daemon(0, 0) < 0)
1.56      ratchov   823:                        err(1, "daemon");
1.15      ratchov   824:        }
1.13      uwe       825:
1.15      ratchov   826:        /*
1.62      ratchov   827:         * Loop, start audio.
1.15      ratchov   828:         */
1.28      ratchov   829:        for (;;) {
1.90      ratchov   830:                if (quit_flag)
1.28      ratchov   831:                        break;
1.92      ratchov   832:                active = 0;
                    833:                for (d = dev_list; d != NULL; d = dnext) {
                    834:                        dnext = d->next;
                    835:                        if (!dev_run(d))
                    836:                                goto fatal;
1.97      jakemsr   837:                        if (d->pstate != DEV_CLOSED && !ctl_idle(d->midi))
1.92      ratchov   838:                                active = 1;
                    839:                }
                    840:                if (dev_list == NULL)
1.50      ratchov   841:                        break;
1.98      ratchov   842:                if (nsock == 0 && !active)
1.83      ratchov   843:                        break;
1.50      ratchov   844:                if (!file_poll())
                    845:                        break;
1.34      ratchov   846:        }
1.92      ratchov   847:   fatal:
1.110     ratchov   848:        listen_closeall();
                    849:
1.90      ratchov   850:        /*
                    851:         * give a chance to drain
                    852:         */
1.96      ratchov   853:        for (d = dev_list; d != NULL; d = d->next)
                    854:                dev_drain(d);
1.90      ratchov   855:        while (file_poll())
                    856:                ; /* nothing */
1.96      ratchov   857:
                    858:        while (dev_list)
                    859:                dev_del(dev_list);
1.83      ratchov   860:        filelist_done();
1.98      ratchov   861:        if (nsock > 0) {
1.86      ratchov   862:                if (rmdir(base) < 0 && errno != ENOTEMPTY && errno != EPERM)
1.55      ratchov   863:                        warn("rmdir(\"%s\")", base);
                    864:        }
1.61      ratchov   865:        unsetsig();
                    866:        return 0;
                    867: }
                    868:
                    869: void
                    870: midicat_usage(void)
                    871: {
1.83      ratchov   872:        (void)fputs("usage: " PROG_MIDICAT " [-dl] "
1.113     ratchov   873:            "[-i file] [-L addr] [-o file] [-q port] [-s name] [-U unit]\n",
1.61      ratchov   874:            stderr);
                    875: }
1.92      ratchov   876:
1.61      ratchov   877: int
                    878: midicat_main(int argc, char **argv)
                    879: {
1.98      ratchov   880:        struct cfdevlist cfdevs;
1.113     ratchov   881:        struct cfnetlist cfnets;
1.92      ratchov   882:        struct cfmid *cm;
1.98      ratchov   883:        struct cfstr *cs;
                    884:        struct cfdev *cd;
1.113     ratchov   885:        struct cfnet *cn;
1.69      ratchov   886:        int c, d_flag, l_flag, unit, fd;
1.61      ratchov   887:        char base[PATH_MAX], path[PATH_MAX];
1.65      ratchov   888:        struct file *stdx;
1.63      ratchov   889:        struct aproc *p;
1.61      ratchov   890:        struct abuf *buf;
1.76      ratchov   891:        const char *str;
1.98      ratchov   892:        struct dev *d, *dnext;
                    893:        unsigned nsock;
1.61      ratchov   894:
1.92      ratchov   895:        /*
                    896:         * global options defaults
                    897:         */
                    898:        unit = -1;
1.69      ratchov   899:        d_flag = 0;
1.61      ratchov   900:        l_flag = 0;
1.98      ratchov   901:        SLIST_INIT(&cfdevs);
1.113     ratchov   902:        SLIST_INIT(&cfnets);
1.98      ratchov   903:        nsock = 0;
                    904:
                    905:        /*
1.116     ratchov   906:         * default device and stream
1.98      ratchov   907:         */
1.116     ratchov   908:        cs = cfstr_new(NULL);
                    909:        cd = cfdev_new(NULL);
1.61      ratchov   910:
1.114     ratchov   911:        while ((c = getopt(argc, argv, "di:o:ls:q:U:L:")) != -1) {
1.61      ratchov   912:                switch (c) {
1.69      ratchov   913:                case 'd':
1.78      ratchov   914: #ifdef DEBUG
                    915:                        if (d_flag)
                    916:                                debug_level++;
                    917: #endif
1.69      ratchov   918:                        d_flag = 1;
                    919:                        break;
1.61      ratchov   920:                case 'i':
1.98      ratchov   921:                        cfstr_add(&cd->ins, cs, optarg);
1.116     ratchov   922:                        cs = cfstr_new(cs);
1.61      ratchov   923:                        break;
                    924:                case 'o':
1.98      ratchov   925:                        cfstr_add(&cd->outs, cs, optarg);
1.116     ratchov   926:                        cs = cfstr_new(cs);
1.61      ratchov   927:                        break;
1.83      ratchov   928:                case 'q':
1.98      ratchov   929:                        cfmid_add(&cd->mids, optarg);
                    930:                        break;
                    931:                case 's':
                    932:                        cfstr_add(&cd->opts, cs, optarg);
                    933:                        cfdev_add(&cfdevs, cd, optarg);
1.116     ratchov   934:                        cd = cfdev_new(cd);
                    935:                        cs = cfstr_new(NULL);
1.98      ratchov   936:                        nsock++;
1.61      ratchov   937:                        break;
                    938:                case 'l':
                    939:                        l_flag = 1;
                    940:                        break;
                    941:                case 'U':
1.76      ratchov   942:                        unit = strtonum(optarg, 0, MIDI_MAXCTL, &str);
                    943:                        if (str)
1.92      ratchov   944:                                errx(1, "%s: unit number is %s", optarg, str);
1.61      ratchov   945:                        break;
1.113     ratchov   946:                case 'L':
                    947:                        cfnet_add(&cfnets, optarg);
                    948:                        break;
1.61      ratchov   949:                default:
                    950:                        midicat_usage();
                    951:                        exit(1);
                    952:                }
                    953:        }
                    954:        argc -= optind;
                    955:        argv += optind;
                    956:
1.98      ratchov   957: #ifdef DEBUG
                    958:        if (debug_level == 0)
                    959:                debug_level = 1;
                    960: #endif
                    961:        if (argc > 0) {
1.61      ratchov   962:                midicat_usage();
                    963:                exit(1);
                    964:        }
1.98      ratchov   965:
                    966:        /*
                    967:         * If there's no device specified (-s), then create one with
                    968:         * reasonable defaults:
                    969:         *
                    970:         *  - if there are no streams (-ioq) defined, assume server mode
                    971:         *    and expose the "defaut" option
                    972:         *
                    973:         *  - if there are files (-io) but no ports (-q) to send/receive
                    974:         *    from, add the default sndio(7) MIDI port
                    975:         */
                    976:        if (SLIST_EMPTY(&cfdevs)) {
                    977:                if (SLIST_EMPTY(&cd->mids)) {
1.116     ratchov   978:                        if (SLIST_EMPTY(&cd->ins) && SLIST_EMPTY(&cd->outs)) {
1.98      ratchov   979:                                cfstr_add(&cd->opts, cs, DEFAULT_OPT);
                    980:                                nsock++;
1.116     ratchov   981:                        } else {
                    982:                                cfmid_add(&cd->mids, "default");
                    983:                                free(cs);
1.98      ratchov   984:                        }
1.116     ratchov   985:                } else
                    986:                        free(cs);
1.98      ratchov   987:                cfdev_add(&cfdevs, cd, "default");
1.116     ratchov   988:        } else {
                    989:                free(cs);
                    990:                free(cd);
1.98      ratchov   991:        }
                    992:        if (nsock > 0) {
1.61      ratchov   993:                getbasepath(base, sizeof(path));
                    994:                if (unit < 0)
                    995:                        unit = 0;
                    996:        }
                    997:        setsig();
                    998:        filelist_init();
                    999:
1.98      ratchov  1000:        while (!SLIST_EMPTY(&cfdevs)) {
                   1001:                cd = SLIST_FIRST(&cfdevs);
                   1002:                SLIST_REMOVE_HEAD(&cfdevs, entry);
                   1003:
                   1004:                d = dev_new_thru();
                   1005:                if (d == NULL)
                   1006:                        errx(1, "%s: can't open device", cd->path);
1.101     ratchov  1007:                if (SLIST_EMPTY(&cd->opts) && APROC_OK(d->midi))
1.98      ratchov  1008:                        d->midi->flags |= APROC_QUIT;
                   1009:
                   1010:                /*
                   1011:                 * register midi ports
                   1012:                 */
                   1013:                while (!SLIST_EMPTY(&cd->mids)) {
                   1014:                        cm = SLIST_FIRST(&cd->mids);
                   1015:                        SLIST_REMOVE_HEAD(&cd->mids, entry);
                   1016:                        if (!dev_thruadd(d, cm->path, 1, 1))
                   1017:                                errx(1, "%s: can't open device", cm->path);
                   1018:                        free(cm);
                   1019:                }
                   1020:
                   1021:                /*
                   1022:                 * register files
                   1023:                 */
                   1024:                while (!SLIST_EMPTY(&cd->ins)) {
                   1025:                        cs = SLIST_FIRST(&cd->ins);
                   1026:                        SLIST_REMOVE_HEAD(&cd->ins, entry);
                   1027:                        if (strcmp(cs->path, "-") == 0) {
                   1028:                                fd = STDIN_FILENO;
                   1029:                                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
                   1030:                                        warn("stdin");
                   1031:                        } else {
                   1032:                                fd = open(cs->path, O_RDONLY | O_NONBLOCK, 0666);
                   1033:                                if (fd < 0)
                   1034:                                        err(1, "%s", cs->path);
                   1035:                        }
                   1036:                        stdx = (struct file *)pipe_new(&pipe_ops, fd, cs->path);
                   1037:                        p = rfile_new(stdx);
                   1038:                        buf = abuf_new(MIDI_BUFSZ, &aparams_none);
                   1039:                        aproc_setout(p, buf);
                   1040:                        dev_midiattach(d, buf, NULL);
                   1041:                        free(cs);
1.77      ratchov  1042:                }
1.98      ratchov  1043:                while (!SLIST_EMPTY(&cd->outs)) {
                   1044:                        cs = SLIST_FIRST(&cd->outs);
                   1045:                        SLIST_REMOVE_HEAD(&cd->outs, entry);
                   1046:                        if (strcmp(cs->path, "-") == 0) {
                   1047:                                fd = STDOUT_FILENO;
                   1048:                                if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
                   1049:                                        warn("stdout");
                   1050:                        } else {
                   1051:                                fd = open(cs->path,
                   1052:                                    O_WRONLY | O_TRUNC | O_CREAT | O_NONBLOCK, 0666);
                   1053:                                if (fd < 0)
                   1054:                                        err(1, "%s", cs->path);
                   1055:                        }
                   1056:                        stdx = (struct file *)pipe_new(&pipe_ops, fd, cs->path);
                   1057:                        p = wfile_new(stdx);
                   1058:                        buf = abuf_new(MIDI_BUFSZ, &aparams_none);
                   1059:                        aproc_setin(p, buf);
                   1060:                        dev_midiattach(d, NULL, buf);
                   1061:                        free(cs);
                   1062:                }
                   1063:                while (!SLIST_EMPTY(&cd->opts)) {
                   1064:                        cs = SLIST_FIRST(&cd->opts);
                   1065:                        SLIST_REMOVE_HEAD(&cd->opts, entry);
1.106     ratchov  1066:                        opt_new(cs->path, d, NULL, NULL, 0, 0, 0, MODE_MIDIMASK);
1.98      ratchov  1067:                        free(cs);
                   1068:                }
                   1069:                free(cd);
1.63      ratchov  1070:        }
1.98      ratchov  1071:        if (nsock > 0) {
1.61      ratchov  1072:                snprintf(path, sizeof(path), "%s/%s%u", base,
1.109     ratchov  1073:                    MIDICAT_PATH, unit);
1.110     ratchov  1074:                listen_new_un(path);
1.113     ratchov  1075:                while (!SLIST_EMPTY(&cfnets)) {
                   1076:                        cn = SLIST_FIRST(&cfnets);
                   1077:                        SLIST_REMOVE_HEAD(&cfnets, entry);
                   1078:                        listen_new_tcp(cn->addr, MIDICAT_PORT + unit);
                   1079:                }
1.98      ratchov  1080:        }
                   1081:        if (geteuid() == 0)
                   1082:                privdrop();
                   1083:        if (l_flag) {
1.107     ratchov  1084: #ifdef DEBUG
1.98      ratchov  1085:                debug_level = 0;
                   1086:                dbg_flush();
1.107     ratchov  1087: #endif
1.98      ratchov  1088:                if (daemon(0, 0) < 0)
1.61      ratchov  1089:                        err(1, "daemon");
                   1090:        }
1.98      ratchov  1091:
1.61      ratchov  1092:        /*
                   1093:         * loop, start processing
                   1094:         */
                   1095:        for (;;) {
1.90      ratchov  1096:                if (quit_flag)
                   1097:                        break;
1.98      ratchov  1098:                for (d = dev_list; d != NULL; d = dnext) {
                   1099:                        dnext = d->next;
                   1100:                        if (!dev_run(d))
                   1101:                                goto fatal;
                   1102:                }
1.61      ratchov  1103:                if (!file_poll())
                   1104:                        break;
                   1105:        }
1.98      ratchov  1106:   fatal:
1.110     ratchov  1107:        listen_closeall();
                   1108:
1.90      ratchov  1109:        /*
1.98      ratchov  1110:         * give a chance to drain
1.90      ratchov  1111:         */
1.98      ratchov  1112:        for (d = dev_list; d != NULL; d = d->next)
                   1113:                dev_drain(d);
1.90      ratchov  1114:        while (file_poll())
                   1115:                ; /* nothing */
1.98      ratchov  1116:
                   1117:        while (dev_list)
                   1118:                dev_del(dev_list);
1.83      ratchov  1119:        filelist_done();
1.98      ratchov  1120:        if (nsock > 0) {
1.86      ratchov  1121:                if (rmdir(base) < 0 && errno != ENOTEMPTY && errno != EPERM)
1.61      ratchov  1122:                        warn("rmdir(\"%s\")", base);
                   1123:        }
                   1124:        unsetsig();
1.15      ratchov  1125:        return 0;
1.61      ratchov  1126: }
                   1127:
                   1128: int
                   1129: main(int argc, char **argv)
                   1130: {
                   1131:        char *prog;
                   1132:
1.90      ratchov  1133: #ifdef DEBUG
                   1134:        atexit(dbg_flush);
                   1135: #endif
1.61      ratchov  1136:        prog = strrchr(argv[0], '/');
                   1137:        if (prog == NULL)
                   1138:                prog = argv[0];
                   1139:        else
                   1140:                prog++;
                   1141:        if (strcmp(prog, PROG_AUCAT) == 0) {
                   1142:                return aucat_main(argc, argv);
                   1143:        } else if (strcmp(prog, PROG_MIDICAT) == 0) {
                   1144:                return midicat_main(argc, argv);
                   1145:        } else {
                   1146:                fprintf(stderr, "%s: can't determine program to run\n", prog);
                   1147:        }
                   1148:        return 1;
1.1       kstailey 1149: }