| File: | src/lib/libossaudio/../libsndio/aucat.c |
| Warning: | line 282, column 2 Null pointer passed as 2nd argument to memory copy function |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: aucat.c,v 1.79 2021/11/07 20:51:47 ratchov Exp $ */ | |||
| 2 | /* | |||
| 3 | * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> | |||
| 4 | * | |||
| 5 | * Permission to use, copy, modify, and distribute this software for any | |||
| 6 | * purpose with or without fee is hereby granted, provided that the above | |||
| 7 | * copyright notice and this permission notice appear in all copies. | |||
| 8 | * | |||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
| 16 | */ | |||
| 17 | ||||
| 18 | #include <sys/types.h> | |||
| 19 | #include <sys/socket.h> | |||
| 20 | #include <sys/stat.h> | |||
| 21 | #include <sys/un.h> | |||
| 22 | ||||
| 23 | #include <netinet/in.h> | |||
| 24 | #include <netinet/tcp.h> | |||
| 25 | #include <netdb.h> | |||
| 26 | ||||
| 27 | #include <errno(*__errno()).h> | |||
| 28 | #include <fcntl.h> | |||
| 29 | #include <limits.h> | |||
| 30 | #include <poll.h> | |||
| 31 | #include <stdio.h> | |||
| 32 | #include <stdlib.h> | |||
| 33 | #include <string.h> | |||
| 34 | #include <unistd.h> | |||
| 35 | ||||
| 36 | #include "aucat.h" | |||
| 37 | #include "debug.h" | |||
| 38 | ||||
| 39 | ||||
| 40 | /* | |||
| 41 | * read a message, return 0 if not completed | |||
| 42 | */ | |||
| 43 | int | |||
| 44 | _aucat_rmsg(struct aucat *hdl, int *eof) | |||
| 45 | { | |||
| 46 | ssize_t n; | |||
| 47 | unsigned char *data; | |||
| 48 | ||||
| 49 | if (hdl->rstate != RSTATE_MSG0) { | |||
| 50 | DPRINTF("_aucat_rmsg: bad state\n")do {} while(0); | |||
| 51 | abort(); | |||
| 52 | } | |||
| 53 | while (hdl->rtodo > 0) { | |||
| 54 | data = (unsigned char *)&hdl->rmsg; | |||
| 55 | data += sizeof(struct amsg) - hdl->rtodo; | |||
| 56 | while ((n = read(hdl->fd, data, hdl->rtodo)) == -1) { | |||
| 57 | if (errno(*__errno()) == EINTR4) | |||
| 58 | continue; | |||
| 59 | if (errno(*__errno()) != EAGAIN35) { | |||
| 60 | *eof = 1; | |||
| 61 | DPERROR("_aucat_rmsg: read")do {} while(0); | |||
| 62 | } | |||
| 63 | return 0; | |||
| 64 | } | |||
| 65 | if (n == 0) { | |||
| 66 | DPRINTF("_aucat_rmsg: eof\n")do {} while(0); | |||
| 67 | *eof = 1; | |||
| 68 | return 0; | |||
| 69 | } | |||
| 70 | hdl->rtodo -= n; | |||
| 71 | } | |||
| 72 | if (ntohl(hdl->rmsg.cmd)(__uint32_t)(__builtin_constant_p(hdl->rmsg.cmd) ? (__uint32_t )(((__uint32_t)(hdl->rmsg.cmd) & 0xff) << 24 | ( (__uint32_t)(hdl->rmsg.cmd) & 0xff00) << 8 | ((__uint32_t )(hdl->rmsg.cmd) & 0xff0000) >> 8 | ((__uint32_t )(hdl->rmsg.cmd) & 0xff000000) >> 24) : __swap32md (hdl->rmsg.cmd)) == AMSG_DATA5) { | |||
| 73 | hdl->rtodo = ntohl(hdl->rmsg.u.data.size)(__uint32_t)(__builtin_constant_p(hdl->rmsg.u.data.size) ? (__uint32_t)(((__uint32_t)(hdl->rmsg.u.data.size) & 0xff ) << 24 | ((__uint32_t)(hdl->rmsg.u.data.size) & 0xff00) << 8 | ((__uint32_t)(hdl->rmsg.u.data.size) & 0xff0000) >> 8 | ((__uint32_t)(hdl->rmsg.u.data .size) & 0xff000000) >> 24) : __swap32md(hdl->rmsg .u.data.size)); | |||
| 74 | hdl->rstate = RSTATE_DATA1; | |||
| 75 | } else { | |||
| 76 | hdl->rtodo = sizeof(struct amsg); | |||
| 77 | hdl->rstate = RSTATE_MSG0; | |||
| 78 | } | |||
| 79 | return 1; | |||
| 80 | } | |||
| 81 | ||||
| 82 | /* | |||
| 83 | * write a message, return 0 if not completed | |||
| 84 | */ | |||
| 85 | int | |||
| 86 | _aucat_wmsg(struct aucat *hdl, int *eof) | |||
| 87 | { | |||
| 88 | ssize_t n; | |||
| 89 | unsigned char *data; | |||
| 90 | ||||
| 91 | if (hdl->wstate == WSTATE_IDLE2) { | |||
| 92 | hdl->wstate = WSTATE_MSG3; | |||
| 93 | hdl->wtodo = sizeof(struct amsg); | |||
| 94 | } | |||
| 95 | if (hdl->wstate != WSTATE_MSG3) { | |||
| 96 | DPRINTF("_aucat_wmsg: bad state\n")do {} while(0); | |||
| 97 | abort(); | |||
| 98 | } | |||
| 99 | while (hdl->wtodo > 0) { | |||
| 100 | data = (unsigned char *)&hdl->wmsg; | |||
| 101 | data += sizeof(struct amsg) - hdl->wtodo; | |||
| 102 | while ((n = write(hdl->fd, data, hdl->wtodo)) == -1) { | |||
| 103 | if (errno(*__errno()) == EINTR4) | |||
| 104 | continue; | |||
| 105 | if (errno(*__errno()) != EAGAIN35) { | |||
| 106 | *eof = 1; | |||
| 107 | DPERROR("_aucat_wmsg: write")do {} while(0); | |||
| 108 | } | |||
| 109 | return 0; | |||
| 110 | } | |||
| 111 | hdl->wtodo -= n; | |||
| 112 | } | |||
| 113 | if (ntohl(hdl->wmsg.cmd)(__uint32_t)(__builtin_constant_p(hdl->wmsg.cmd) ? (__uint32_t )(((__uint32_t)(hdl->wmsg.cmd) & 0xff) << 24 | ( (__uint32_t)(hdl->wmsg.cmd) & 0xff00) << 8 | ((__uint32_t )(hdl->wmsg.cmd) & 0xff0000) >> 8 | ((__uint32_t )(hdl->wmsg.cmd) & 0xff000000) >> 24) : __swap32md (hdl->wmsg.cmd)) == AMSG_DATA5) { | |||
| 114 | hdl->wtodo = ntohl(hdl->wmsg.u.data.size)(__uint32_t)(__builtin_constant_p(hdl->wmsg.u.data.size) ? (__uint32_t)(((__uint32_t)(hdl->wmsg.u.data.size) & 0xff ) << 24 | ((__uint32_t)(hdl->wmsg.u.data.size) & 0xff00) << 8 | ((__uint32_t)(hdl->wmsg.u.data.size) & 0xff0000) >> 8 | ((__uint32_t)(hdl->wmsg.u.data .size) & 0xff000000) >> 24) : __swap32md(hdl->wmsg .u.data.size)); | |||
| 115 | hdl->wstate = WSTATE_DATA4; | |||
| 116 | } else { | |||
| 117 | hdl->wtodo = 0xdeadbeef; | |||
| 118 | hdl->wstate = WSTATE_IDLE2; | |||
| 119 | } | |||
| 120 | return 1; | |||
| 121 | } | |||
| 122 | ||||
| 123 | size_t | |||
| 124 | _aucat_rdata(struct aucat *hdl, void *buf, size_t len, int *eof) | |||
| 125 | { | |||
| 126 | ssize_t n; | |||
| 127 | ||||
| 128 | if (hdl->rstate != RSTATE_DATA1) { | |||
| 129 | DPRINTF("_aucat_rdata: bad state\n")do {} while(0); | |||
| 130 | abort(); | |||
| 131 | } | |||
| 132 | if (len > hdl->rtodo) | |||
| 133 | len = hdl->rtodo; | |||
| 134 | while ((n = read(hdl->fd, buf, len)) == -1) { | |||
| 135 | if (errno(*__errno()) == EINTR4) | |||
| 136 | continue; | |||
| 137 | if (errno(*__errno()) != EAGAIN35) { | |||
| 138 | *eof = 1; | |||
| 139 | DPERROR("_aucat_rdata: read")do {} while(0); | |||
| 140 | } | |||
| 141 | return 0; | |||
| 142 | } | |||
| 143 | if (n == 0) { | |||
| 144 | DPRINTF("_aucat_rdata: eof\n")do {} while(0); | |||
| 145 | *eof = 1; | |||
| 146 | return 0; | |||
| 147 | } | |||
| 148 | hdl->rtodo -= n; | |||
| 149 | if (hdl->rtodo == 0) { | |||
| 150 | hdl->rstate = RSTATE_MSG0; | |||
| 151 | hdl->rtodo = sizeof(struct amsg); | |||
| 152 | } | |||
| 153 | DPRINTFN(2, "_aucat_rdata: read: n = %zd\n", n)do {} while(0); | |||
| 154 | return n; | |||
| 155 | } | |||
| 156 | ||||
| 157 | size_t | |||
| 158 | _aucat_wdata(struct aucat *hdl, const void *buf, size_t len, | |||
| 159 | unsigned int wbpf, int *eof) | |||
| 160 | { | |||
| 161 | ssize_t n; | |||
| 162 | size_t datasize; | |||
| 163 | ||||
| 164 | switch (hdl->wstate) { | |||
| 165 | case WSTATE_IDLE2: | |||
| 166 | datasize = len; | |||
| 167 | if (datasize > AMSG_DATAMAX0x1000) | |||
| 168 | datasize = AMSG_DATAMAX0x1000; | |||
| 169 | datasize -= datasize % wbpf; | |||
| 170 | if (datasize == 0) | |||
| 171 | datasize = wbpf; | |||
| 172 | hdl->wmsg.cmd = htonl(AMSG_DATA)(__uint32_t)(__builtin_constant_p(5) ? (__uint32_t)(((__uint32_t )(5) & 0xff) << 24 | ((__uint32_t)(5) & 0xff00) << 8 | ((__uint32_t)(5) & 0xff0000) >> 8 | ( (__uint32_t)(5) & 0xff000000) >> 24) : __swap32md(5 )); | |||
| 173 | hdl->wmsg.u.data.size = htonl(datasize)(__uint32_t)(__builtin_constant_p(datasize) ? (__uint32_t)((( __uint32_t)(datasize) & 0xff) << 24 | ((__uint32_t) (datasize) & 0xff00) << 8 | ((__uint32_t)(datasize) & 0xff0000) >> 8 | ((__uint32_t)(datasize) & 0xff000000 ) >> 24) : __swap32md(datasize)); | |||
| 174 | hdl->wtodo = sizeof(struct amsg); | |||
| 175 | hdl->wstate = WSTATE_MSG3; | |||
| 176 | /* FALLTHROUGH */ | |||
| 177 | case WSTATE_MSG3: | |||
| 178 | if (!_aucat_wmsg(hdl, eof)) | |||
| 179 | return 0; | |||
| 180 | } | |||
| 181 | if (len > hdl->wtodo) | |||
| 182 | len = hdl->wtodo; | |||
| 183 | if (len == 0) { | |||
| 184 | DPRINTF("_aucat_wdata: len == 0\n")do {} while(0); | |||
| 185 | abort(); | |||
| 186 | } | |||
| 187 | while ((n = write(hdl->fd, buf, len)) == -1) { | |||
| 188 | if (errno(*__errno()) == EINTR4) | |||
| 189 | continue; | |||
| 190 | if (errno(*__errno()) != EAGAIN35) { | |||
| 191 | *eof = 1; | |||
| 192 | DPERROR("_aucat_wdata: write")do {} while(0); | |||
| 193 | } | |||
| 194 | return 0; | |||
| 195 | } | |||
| 196 | DPRINTFN(2, "_aucat_wdata: write: n = %zd\n", n)do {} while(0); | |||
| 197 | hdl->wtodo -= n; | |||
| 198 | if (hdl->wtodo == 0) { | |||
| 199 | hdl->wstate = WSTATE_IDLE2; | |||
| 200 | hdl->wtodo = 0xdeadbeef; | |||
| 201 | } | |||
| 202 | return n; | |||
| 203 | } | |||
| 204 | ||||
| 205 | static int | |||
| 206 | aucat_mkcookie(unsigned char *cookie) | |||
| 207 | { | |||
| 208 | #define COOKIE_DIR"/.sndio" "/.sndio" | |||
| 209 | #define COOKIE_SUFFIX"/.sndio/cookie" "/.sndio/cookie" | |||
| 210 | #define TEMPL_SUFFIX".XXXXXXXX" ".XXXXXXXX" | |||
| 211 | struct stat sb; | |||
| 212 | char *home, *path = NULL((void *)0), *tmp = NULL((void *)0); | |||
| 213 | size_t home_len, path_len; | |||
| 214 | int fd, len; | |||
| 215 | ||||
| 216 | /* please gcc */ | |||
| 217 | path_len = 0xdeadbeef; | |||
| 218 | ||||
| 219 | /* | |||
| 220 | * try to load the cookie | |||
| 221 | */ | |||
| 222 | home = issetugid() ? NULL((void *)0) : getenv("HOME"); | |||
| 223 | if (home == NULL((void *)0)) | |||
| 224 | goto bad_gen; | |||
| 225 | home_len = strlen(home); | |||
| 226 | path = malloc(home_len + sizeof(COOKIE_SUFFIX"/.sndio/cookie")); | |||
| 227 | if (path == NULL((void *)0)) | |||
| 228 | goto bad_gen; | |||
| 229 | memcpy(path, home, home_len); | |||
| 230 | memcpy(path + home_len, COOKIE_SUFFIX"/.sndio/cookie", sizeof(COOKIE_SUFFIX"/.sndio/cookie")); | |||
| 231 | path_len = home_len + sizeof(COOKIE_SUFFIX"/.sndio/cookie") - 1; | |||
| 232 | fd = open(path, O_RDONLY0x0000); | |||
| 233 | if (fd == -1) { | |||
| 234 | if (errno(*__errno()) != ENOENT2) | |||
| 235 | DPERROR(path)do {} while(0); | |||
| 236 | goto bad_gen; | |||
| 237 | } | |||
| 238 | if (fstat(fd, &sb) == -1) { | |||
| 239 | DPERROR(path)do {} while(0); | |||
| 240 | goto bad_close; | |||
| 241 | } | |||
| 242 | if (sb.st_mode & 0077) { | |||
| 243 | DPRINTF("%s has wrong permissions\n", path)do {} while(0); | |||
| 244 | goto bad_close; | |||
| 245 | } | |||
| 246 | len = read(fd, cookie, AMSG_COOKIELEN16); | |||
| 247 | if (len == -1) { | |||
| 248 | DPERROR(path)do {} while(0); | |||
| 249 | goto bad_close; | |||
| 250 | } | |||
| 251 | if (len != AMSG_COOKIELEN16) { | |||
| 252 | DPRINTF("%s: short read\n", path)do {} while(0); | |||
| 253 | goto bad_close; | |||
| 254 | } | |||
| 255 | close(fd); | |||
| 256 | goto done; | |||
| 257 | bad_close: | |||
| 258 | close(fd); | |||
| 259 | bad_gen: | |||
| 260 | /* | |||
| 261 | * generate a new cookie | |||
| 262 | */ | |||
| 263 | arc4random_buf(cookie, AMSG_COOKIELEN16); | |||
| 264 | ||||
| 265 | /* | |||
| 266 | * try to save the cookie | |||
| 267 | */ | |||
| 268 | ||||
| 269 | if (home
| |||
| 270 | goto done; | |||
| 271 | tmp = malloc(path_len + sizeof(TEMPL_SUFFIX".XXXXXXXX")); | |||
| 272 | if (tmp == NULL((void *)0)) | |||
| 273 | goto done; | |||
| 274 | ||||
| 275 | /* create ~/.sndio directory */ | |||
| 276 | memcpy(tmp, home, home_len); | |||
| 277 | memcpy(tmp + home_len, COOKIE_DIR"/.sndio", sizeof(COOKIE_DIR"/.sndio")); | |||
| 278 | if (mkdir(tmp, 0755) == -1 && errno(*__errno()) != EEXIST17) | |||
| 279 | goto done; | |||
| 280 | ||||
| 281 | /* create cookie file in it */ | |||
| 282 | memcpy(tmp, path, path_len); | |||
| ||||
| 283 | memcpy(tmp + path_len, TEMPL_SUFFIX".XXXXXXXX", sizeof(TEMPL_SUFFIX".XXXXXXXX")); | |||
| 284 | fd = mkstemp(tmp); | |||
| 285 | if (fd == -1) { | |||
| 286 | DPERROR(tmp)do {} while(0); | |||
| 287 | goto done; | |||
| 288 | } | |||
| 289 | if (write(fd, cookie, AMSG_COOKIELEN16) == -1) { | |||
| 290 | DPERROR(tmp)do {} while(0); | |||
| 291 | unlink(tmp); | |||
| 292 | close(fd); | |||
| 293 | goto done; | |||
| 294 | } | |||
| 295 | close(fd); | |||
| 296 | if (rename(tmp, path) == -1) { | |||
| 297 | DPERROR(tmp)do {} while(0); | |||
| 298 | unlink(tmp); | |||
| 299 | } | |||
| 300 | done: | |||
| 301 | free(tmp); | |||
| 302 | free(path); | |||
| 303 | return 1; | |||
| 304 | } | |||
| 305 | ||||
| 306 | static int | |||
| 307 | aucat_connect_tcp(struct aucat *hdl, char *host, unsigned int unit) | |||
| 308 | { | |||
| 309 | int s, error, opt; | |||
| 310 | struct addrinfo *ailist, *ai, aihints; | |||
| 311 | char serv[NI_MAXSERV32]; | |||
| 312 | ||||
| 313 | snprintf(serv, sizeof(serv), "%u", unit + AUCAT_PORT11025); | |||
| 314 | memset(&aihints, 0, sizeof(struct addrinfo)); | |||
| 315 | aihints.ai_socktype = SOCK_STREAM1; | |||
| 316 | aihints.ai_protocol = IPPROTO_TCP6; | |||
| 317 | error = getaddrinfo(host, serv, &aihints, &ailist); | |||
| 318 | if (error) { | |||
| 319 | DPRINTF("%s: %s\n", host, gai_strerror(error))do {} while(0); | |||
| 320 | return 0; | |||
| 321 | } | |||
| 322 | s = -1; | |||
| 323 | for (ai = ailist; ai != NULL((void *)0); ai = ai->ai_next) { | |||
| 324 | s = socket(ai->ai_family, ai->ai_socktype | SOCK_CLOEXEC0x8000, | |||
| 325 | ai->ai_protocol); | |||
| 326 | if (s == -1) { | |||
| 327 | DPERROR("socket")do {} while(0); | |||
| 328 | continue; | |||
| 329 | } | |||
| 330 | restart: | |||
| 331 | if (connect(s, ai->ai_addr, ai->ai_addrlen) == -1) { | |||
| 332 | if (errno(*__errno()) == EINTR4) | |||
| 333 | goto restart; | |||
| 334 | DPERROR("connect")do {} while(0); | |||
| 335 | close(s); | |||
| 336 | s = -1; | |||
| 337 | continue; | |||
| 338 | } | |||
| 339 | break; | |||
| 340 | } | |||
| 341 | freeaddrinfo(ailist); | |||
| 342 | if (s == -1) | |||
| 343 | return 0; | |||
| 344 | opt = 1; | |||
| 345 | if (setsockopt(s, IPPROTO_TCP6, TCP_NODELAY0x01, &opt, sizeof(int)) == -1) { | |||
| 346 | DPERROR("setsockopt")do {} while(0); | |||
| 347 | close(s); | |||
| 348 | return 0; | |||
| 349 | } | |||
| 350 | hdl->fd = s; | |||
| 351 | return 1; | |||
| 352 | } | |||
| 353 | ||||
| 354 | static int | |||
| 355 | aucat_connect_un(struct aucat *hdl, unsigned int unit) | |||
| 356 | { | |||
| 357 | struct sockaddr_un ca; | |||
| 358 | socklen_t len = sizeof(struct sockaddr_un); | |||
| 359 | uid_t uid; | |||
| 360 | int s; | |||
| 361 | ||||
| 362 | uid = geteuid(); | |||
| 363 | snprintf(ca.sun_path, sizeof(ca.sun_path), | |||
| 364 | SOCKPATH_DIR"/tmp/sndio" "-%u/" SOCKPATH_FILE"sock" "%u", uid, unit); | |||
| 365 | ca.sun_family = AF_UNIX1; | |||
| 366 | s = socket(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000, 0); | |||
| 367 | if (s == -1) | |||
| 368 | return 0; | |||
| 369 | while (connect(s, (struct sockaddr *)&ca, len) == -1) { | |||
| 370 | if (errno(*__errno()) == EINTR4) | |||
| 371 | continue; | |||
| 372 | DPERROR(ca.sun_path)do {} while(0); | |||
| 373 | /* try shared server */ | |||
| 374 | snprintf(ca.sun_path, sizeof(ca.sun_path), | |||
| 375 | SOCKPATH_DIR"/tmp/sndio" "/" SOCKPATH_FILE"sock" "%u", unit); | |||
| 376 | while (connect(s, (struct sockaddr *)&ca, len) == -1) { | |||
| 377 | if (errno(*__errno()) == EINTR4) | |||
| 378 | continue; | |||
| 379 | DPERROR(ca.sun_path)do {} while(0); | |||
| 380 | close(s); | |||
| 381 | return 0; | |||
| 382 | } | |||
| 383 | break; | |||
| 384 | } | |||
| 385 | hdl->fd = s; | |||
| 386 | DPRINTFN(2, "%s: connected\n", ca.sun_path)do {} while(0); | |||
| 387 | return 1; | |||
| 388 | } | |||
| 389 | ||||
| 390 | static const char * | |||
| 391 | parsestr(const char *str, char *rstr, unsigned int max) | |||
| 392 | { | |||
| 393 | const char *p = str; | |||
| 394 | ||||
| 395 | while (*p != '\0' && *p != ',' && *p != '/') { | |||
| 396 | if (--max == 0) { | |||
| 397 | DPRINTF("%s: string too long\n", str)do {} while(0); | |||
| 398 | return NULL((void *)0); | |||
| 399 | } | |||
| 400 | *rstr++ = *p++; | |||
| 401 | } | |||
| 402 | if (str == p) { | |||
| 403 | DPRINTF("%s: string expected\n", str)do {} while(0); | |||
| 404 | return NULL((void *)0); | |||
| 405 | } | |||
| 406 | *rstr = '\0'; | |||
| 407 | return p; | |||
| 408 | } | |||
| 409 | ||||
| 410 | int | |||
| 411 | _aucat_open(struct aucat *hdl, const char *str, unsigned int mode) | |||
| 412 | { | |||
| 413 | extern char *__progname; | |||
| 414 | int eof; | |||
| 415 | char host[NI_MAXHOST256], opt[AMSG_OPTMAX12]; | |||
| 416 | const char *p; | |||
| 417 | unsigned int unit, devnum, type; | |||
| 418 | ||||
| 419 | if ((p = _sndio_parsetype(str, "snd")) != NULL((void *)0)) | |||
| ||||
| 420 | type = 0; | |||
| 421 | else if ((p = _sndio_parsetype(str, "midithru")) != NULL((void *)0)) | |||
| 422 | type = 1; | |||
| 423 | else if ((p = _sndio_parsetype(str, "midi")) != NULL((void *)0)) | |||
| 424 | type = 2; | |||
| 425 | else { | |||
| 426 | DPRINTF("%s: unsupported device type\n", str)do {} while(0); | |||
| 427 | return -1; | |||
| 428 | } | |||
| 429 | if (*p == '@') { | |||
| 430 | p = parsestr(++p, host, NI_MAXHOST256); | |||
| 431 | if (p == NULL((void *)0)) | |||
| 432 | return 0; | |||
| 433 | } else | |||
| 434 | *host = '\0'; | |||
| 435 | if (*p == ',') { | |||
| 436 | p = _sndio_parsenum(++p, &unit, 15); | |||
| 437 | if (p == NULL((void *)0)) | |||
| 438 | return 0; | |||
| 439 | } else | |||
| 440 | unit = 0; | |||
| 441 | if (*p != '/') { | |||
| 442 | DPRINTF("%s: '/' expected\n", str)do {} while(0); | |||
| 443 | return 0; | |||
| 444 | } | |||
| 445 | p++; | |||
| 446 | if (type
| |||
| 447 | if (*p < '0' || *p > '9') { | |||
| 448 | devnum = AMSG_NODEV255; | |||
| 449 | p = parsestr(p, opt, AMSG_OPTMAX12); | |||
| 450 | if (p == NULL((void *)0)) | |||
| 451 | return 0; | |||
| 452 | } else { | |||
| 453 | p = _sndio_parsenum(p, &devnum, 15); | |||
| 454 | if (p == NULL((void *)0)) | |||
| 455 | return 0; | |||
| 456 | if (*p == '.') { | |||
| 457 | p = parsestr(++p, opt, AMSG_OPTMAX12); | |||
| 458 | if (p == NULL((void *)0)) | |||
| 459 | return 0; | |||
| 460 | } else | |||
| 461 | strlcpy(opt, "default", AMSG_OPTMAX12); | |||
| 462 | } | |||
| 463 | } else { | |||
| 464 | p = _sndio_parsenum(p, &devnum, 15); | |||
| 465 | if (p == NULL((void *)0)) | |||
| 466 | return 0; | |||
| 467 | memset(opt, 0, sizeof(opt)); | |||
| 468 | } | |||
| 469 | if (*p != '\0') { | |||
| 470 | DPRINTF("%s: junk at end of dev name\n", p)do {} while(0); | |||
| 471 | return 0; | |||
| 472 | } | |||
| 473 | devnum += type * 16; /* XXX */ | |||
| 474 | DPRINTFN(2, "_aucat_open: host=%s unit=%u devnum=%u opt=%s\n",do {} while(0) | |||
| 475 | host, unit, devnum, opt)do {} while(0); | |||
| 476 | if (host[0] != '\0') { | |||
| 477 | if (!aucat_connect_tcp(hdl, host, unit)) | |||
| 478 | return 0; | |||
| 479 | } else { | |||
| 480 | if (!aucat_connect_un(hdl, unit)) | |||
| 481 | return 0; | |||
| 482 | } | |||
| 483 | hdl->rstate = RSTATE_MSG0; | |||
| 484 | hdl->rtodo = sizeof(struct amsg); | |||
| 485 | hdl->wstate = WSTATE_IDLE2; | |||
| 486 | hdl->wtodo = 0xdeadbeef; | |||
| 487 | hdl->maxwrite = 0; | |||
| 488 | ||||
| 489 | /* | |||
| 490 | * say hello to server | |||
| 491 | */ | |||
| 492 | AMSG_INIT(&hdl->wmsg)do { memset((&hdl->wmsg), 0xff, sizeof(struct amsg)); } while (0); | |||
| 493 | hdl->wmsg.cmd = htonl(AMSG_AUTH)(__uint32_t)(__builtin_constant_p(12) ? (__uint32_t)(((__uint32_t )(12) & 0xff) << 24 | ((__uint32_t)(12) & 0xff00 ) << 8 | ((__uint32_t)(12) & 0xff0000) >> 8 | ((__uint32_t)(12) & 0xff000000) >> 24) : __swap32md (12)); | |||
| 494 | if (!aucat_mkcookie(hdl->wmsg.u.auth.cookie)) | |||
| 495 | goto bad_connect; | |||
| 496 | hdl->wtodo = sizeof(struct amsg); | |||
| 497 | if (!_aucat_wmsg(hdl, &eof)) | |||
| 498 | goto bad_connect; | |||
| 499 | AMSG_INIT(&hdl->wmsg)do { memset((&hdl->wmsg), 0xff, sizeof(struct amsg)); } while (0); | |||
| 500 | hdl->wmsg.cmd = htonl(AMSG_HELLO)(__uint32_t)(__builtin_constant_p(10) ? (__uint32_t)(((__uint32_t )(10) & 0xff) << 24 | ((__uint32_t)(10) & 0xff00 ) << 8 | ((__uint32_t)(10) & 0xff0000) >> 8 | ((__uint32_t)(10) & 0xff000000) >> 24) : __swap32md (10)); | |||
| 501 | hdl->wmsg.u.hello.version = AMSG_VERSION7; | |||
| 502 | hdl->wmsg.u.hello.mode = htons(mode)(__uint16_t)(__builtin_constant_p(mode) ? (__uint16_t)(((__uint16_t )(mode) & 0xffU) << 8 | ((__uint16_t)(mode) & 0xff00U ) >> 8) : __swap16md(mode)); | |||
| 503 | hdl->wmsg.u.hello.devnum = devnum; | |||
| 504 | hdl->wmsg.u.hello.id = htonl(getpid())(__uint32_t)(__builtin_constant_p(getpid()) ? (__uint32_t)((( __uint32_t)(getpid()) & 0xff) << 24 | ((__uint32_t) (getpid()) & 0xff00) << 8 | ((__uint32_t)(getpid()) & 0xff0000) >> 8 | ((__uint32_t)(getpid()) & 0xff000000 ) >> 24) : __swap32md(getpid())); | |||
| 505 | strlcpy(hdl->wmsg.u.hello.who, __progname, | |||
| 506 | sizeof(hdl->wmsg.u.hello.who)); | |||
| 507 | strlcpy(hdl->wmsg.u.hello.opt, opt, | |||
| 508 | sizeof(hdl->wmsg.u.hello.opt)); | |||
| 509 | hdl->wtodo = sizeof(struct amsg); | |||
| 510 | if (!_aucat_wmsg(hdl, &eof)) | |||
| 511 | goto bad_connect; | |||
| 512 | hdl->rtodo = sizeof(struct amsg); | |||
| 513 | if (!_aucat_rmsg(hdl, &eof)) { | |||
| 514 | DPRINTF("aucat_init: mode refused\n")do {} while(0); | |||
| 515 | goto bad_connect; | |||
| 516 | } | |||
| 517 | if (ntohl(hdl->rmsg.cmd)(__uint32_t)(__builtin_constant_p(hdl->rmsg.cmd) ? (__uint32_t )(((__uint32_t)(hdl->rmsg.cmd) & 0xff) << 24 | ( (__uint32_t)(hdl->rmsg.cmd) & 0xff00) << 8 | ((__uint32_t )(hdl->rmsg.cmd) & 0xff0000) >> 8 | ((__uint32_t )(hdl->rmsg.cmd) & 0xff000000) >> 24) : __swap32md (hdl->rmsg.cmd)) != AMSG_ACK0) { | |||
| 518 | DPRINTF("aucat_init: protocol err\n")do {} while(0); | |||
| 519 | goto bad_connect; | |||
| 520 | } | |||
| 521 | return 1; | |||
| 522 | bad_connect: | |||
| 523 | while (close(hdl->fd) == -1 && errno(*__errno()) == EINTR4) | |||
| 524 | ; /* retry */ | |||
| 525 | return 0; | |||
| 526 | } | |||
| 527 | ||||
| 528 | void | |||
| 529 | _aucat_close(struct aucat *hdl, int eof) | |||
| 530 | { | |||
| 531 | char dummy[sizeof(struct amsg)]; | |||
| 532 | ssize_t n; | |||
| 533 | ||||
| 534 | if (!eof) { | |||
| 535 | AMSG_INIT(&hdl->wmsg)do { memset((&hdl->wmsg), 0xff, sizeof(struct amsg)); } while (0); | |||
| 536 | hdl->wmsg.cmd = htonl(AMSG_BYE)(__uint32_t)(__builtin_constant_p(11) ? (__uint32_t)(((__uint32_t )(11) & 0xff) << 24 | ((__uint32_t)(11) & 0xff00 ) << 8 | ((__uint32_t)(11) & 0xff0000) >> 8 | ((__uint32_t)(11) & 0xff000000) >> 24) : __swap32md (11)); | |||
| 537 | hdl->wtodo = sizeof(struct amsg); | |||
| 538 | if (!_aucat_wmsg(hdl, &eof)) | |||
| 539 | goto bad_close; | |||
| 540 | ||||
| 541 | /* | |||
| 542 | * block until the peer disconnects | |||
| 543 | */ | |||
| 544 | while (1) { | |||
| 545 | n = read(hdl->fd, dummy, sizeof(dummy)); | |||
| 546 | if (n == -1) { | |||
| 547 | if (errno(*__errno()) == EINTR4) | |||
| 548 | continue; | |||
| 549 | break; | |||
| 550 | } | |||
| 551 | if (n == 0) | |||
| 552 | break; | |||
| 553 | } | |||
| 554 | } | |||
| 555 | bad_close: | |||
| 556 | while (close(hdl->fd) == -1 && errno(*__errno()) == EINTR4) | |||
| 557 | ; /* nothing */ | |||
| 558 | } | |||
| 559 | ||||
| 560 | int | |||
| 561 | _aucat_setfl(struct aucat *hdl, int nbio, int *eof) | |||
| 562 | { | |||
| 563 | if (fcntl(hdl->fd, F_SETFL4, nbio ? O_NONBLOCK0x0004 : 0) == -1) { | |||
| 564 | DPERROR("_aucat_setfl: fcntl")do {} while(0); | |||
| 565 | *eof = 1; | |||
| 566 | return 0; | |||
| 567 | } | |||
| 568 | return 1; | |||
| 569 | } | |||
| 570 | ||||
| 571 | int | |||
| 572 | _aucat_pollfd(struct aucat *hdl, struct pollfd *pfd, int events) | |||
| 573 | { | |||
| 574 | if (hdl->rstate == RSTATE_MSG0) | |||
| 575 | events |= POLLIN0x0001; | |||
| 576 | pfd->fd = hdl->fd; | |||
| 577 | pfd->events = events; | |||
| 578 | return 1; | |||
| 579 | } | |||
| 580 | ||||
| 581 | int | |||
| 582 | _aucat_revents(struct aucat *hdl, struct pollfd *pfd) | |||
| 583 | { | |||
| 584 | int revents = pfd->revents; | |||
| 585 | ||||
| 586 | DPRINTFN(2, "_aucat_revents: revents: %x\n", revents)do {} while(0); | |||
| 587 | return revents; | |||
| 588 | } |