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

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