X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-utils.git;a=blobdiff_plain;f=cprogs%2Ftrivsoundd.c;h=a7bed2c7021bea537fb01b91188dc8bfc2e2fbf9;hp=5eda4f7aebd098427c30a439fa8348d60ee9b23a;hb=35b7f048aa1f639d485ce7e6b4ff4ef6274f91b3;hpb=e483a046db5ff0972702a0dc29ba4e00b698d997 diff --git a/cprogs/trivsoundd.c b/cprogs/trivsoundd.c index 5eda4f7..a7bed2c 100644 --- a/cprogs/trivsoundd.c +++ b/cprogs/trivsoundd.c @@ -40,9 +40,88 @@ struct inqnode { }; static struct { struct inqnode *head, *tail; } inq; -static int sdev; +static int master, sdev; static time_t now; +static void usageerr(const char *m) { + fprintf(stderr,"bad usage: %s\n",m); + exit(12); +} + +static void bindmaster(const char *bindname) { + union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_un sun; + } su; + socklen_t sulen; + const char *colon; + char *copy, *ep; + int r; + unsigned long portul; + struct hostent *he; + struct servent *se; + + memset(&su,0,sizeof(su)); + + if (bindname[0]=='/' || bindname[0]=='.') { + + if (strlen(bindname) >= sizeof(su.sun.sun_path)) + usageerr("AF_UNIX bind path too long"); + sulen= sizeof(su.sun); + su.sun.sun_family= AF_UNIX; + strcpy(su.sun.sun_path, bindname); + + } else if (bindname[0] != ':' && (colon= strrchr(bindname,':'))) { + + sulen= sizeof(su.sin); + su.sin.sin_family= AF_INET; + + copy= xmalloc(colon - bindname + 1); + memcpy(copy,bindname, colon - bindname + 1); + copy[colon - bindname]= 0; + portul= strtoul(colon+1,&ep,0); + + if (!*ep) { + if (!portul || portul>=65536) usageerr("invalid port number"); + su.sin.sin_port= htons(portul); + } else { + se= getservbyname(colon+1, "tcp"); + if (!se) { fprintf(stderr,"unknown service `%s'\n",colon+1); exit(4); } + su.sin.sin_port= htons(se->s_port); + } + + if (!strcmp(copy,"any")) { + su.sin.sin_addr.s_addr= INADDR_ANY; + } else if (!inet_aton(copy,&su.sin.sin_addr)) { + he= gethostbyname(copy); + if (!he) { herror(copy); exit(4); } + if (he->h_addrtype != AF_INET || + he->h_length != sizeof(su.sin.sin_addr) || + !he->h_addr_list[0] || + he->h_addr_list[1]) { + fprintf(stderr,"hostname lookup `%s' did not yield" + " exactly one IPv4 address\n",copy); + exit(4); + } + memcpy(&su.sin.sin_addr, he->h_addr_list[0], sizeof(su.sin.sin_addr)); + } + + } else { + usageerr("unknown bind name"); + exit(12); + } + + master= socket(su.sa.sa_family,SOCK_STREAM,0); + if (master<0) { perror("socket"); exit(8); } + + r= bind(master, &su.sa, sulen); + if (r) { perror("bind"); exit(8); } + + r= listen(master, 5); + if (r) { perror("listen"); exit(8); } +} + static void opensounddevice(void) { int r; char cbuf[200]; @@ -55,10 +134,14 @@ static void opensounddevice(void) { r= system(cbuf); if (r) { fprintf(stderr,"sox gave %d\n",r); exit(5); } } +void wrbuf_report(const char *m) { + printf("writing %s\n", m); +} + static void selectcopy(void) { int slave= inq.head ? inq.head->fd : -1; wrbufcore_prepselect(slave, sdev); - FD_SET(0,&readfds); + fdsetset(master,&readfds); callselect(); wrbufcore_afterselect(slave, sdev); } @@ -69,7 +152,7 @@ static void expireoldconns(void) { for (searchold= inq.head ? inq.head->next : 0; searchold; searchold= nextsearchold) { - nextsearchold= searchold; + nextsearchold= searchold->next; if (searchold->accepted < now-maxstartdelay) { printf("expired %p\n",searchold); LIST_UNLINK(inq,searchold); @@ -84,9 +167,9 @@ static void acceptnewconns(void) { int slave; struct inqnode *new; - if (!FD_ISSET(0,&readfds)) return; + if (!FD_ISSET(master,&readfds)) return; - slave= accept(0,0,0); + slave= accept(master,0,0); if (slave < 0) { if (!(errno == EINTR || errno == EAGAIN || @@ -125,13 +208,15 @@ static void switchinput(void) { int main(int argc, const char *const *argv) { assert(argv[0]); - if (argv[1]) { fputs("no arguments allowed\n",stderr); exit(12); } + if (!argv[1] || argv[2] || argv[1][0]=='-') + usageerr("no options allowed, must have one argument (bindname)"); buffersize= 44100*4* 5/*seconds*/; opensounddevice(); + bindmaster(argv[1]); nonblock(sdev,1); - nonblock(0,1); + nonblock(master,1); startupcore(); wrbufcore_startup();