chiark / gitweb /
e3d1acf06a9769d1703ff946fbb511315ec499a0
[chiark-utils.git] / cprogs / trivsoundd.c
1 /*
2  * triv-sound-d.c
3  * writebuffer adapted for sound-playing
4  *
5  * readbuffer and writebuffer are:
6  *  Copyright (C) 1997-1998,2000-2001 Ian Jackson <ian@chiark.greenend.org.uk>
7  *
8  * readbuffer is part of chiark backup, a system for backing up GNU/Linux and
9  * other UN*X-compatible machines, as used on chiark.greenend.org.uk.
10  * chiark backup is:
11  *  Copyright (C) 1997-1998,2000-2001 Ian Jackson <ian@chiark.greenend.org.uk>
12  *  Copyright (C) 1999 Peter Maydell <pmaydell@chiark.greenend.org.uk>
13  *
14  * This is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as
16  * published by the Free Software Foundation; either version 2,
17  * or (at your option) any later version.
18  *
19  * This is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public
25  * License along with this file; if not, write to the Free Software
26  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27  *
28  */
29
30 #include <sys/time.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <stdio.h>
35 #include <assert.h>
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <errno.h>
39 #include <sys/mman.h>
40
41 #include "rwbuffer.h"
42
43 const char *progname= "triv-sound-d";
44
45 static int master;
46
47 int main(int argc, const char *const *argv) {
48   const char *bindname;
49   union {
50     struct sockaddr sa;
51     struct sockaddr_in sin;
52     struct sockaddr_un sun;
53   } su;
54   socklen_t sulen;
55
56   bindname= *++argv;
57   if (!bindname) usageerr("need bind argument");
58   startup(argv);
59
60   memset(&su,0,sizeof(su));
61
62   if (bindname[0]=='/' || bindname[0]='.') {
63     if (strlen(bindname) >= sizeof(su.sun.sun_path))
64       usageerr("AF_UNIX bind path too long");
65     sulen= sizeof(su.sun);
66     su.sun.sun_family= AF_UNIX;
67     strcpy(su.sun.sun_path, bindname);
68   } else if ((colon= strrchr(bindname,':'))) {
69     char *copy, *ep;
70     unsigned long portul;
71
72     sulen= sizeof(su.sin);
73     su.sin.sin_family= AF_INET;
74
75     copy= xmalloc(colon - bindname + 1);
76     memcpy(copy,bindname, colon - bindname + 1);
77     copy[colon - bindname]= 0;
78     portul= strtoul(colon+1,0,&ep);
79     if (!*ep) {
80       if (!portul || portul>=65536) usageerr("invalid port number");
81       su.sin.sin_port= htons(portul);
82     } else {
83       struct servent *se= getservbyname(colon+1, "tcp");
84       if (!se) { fprintf(stderr,"unknown service `%s'\n",colon+1); exit(4); }
85       su.sin.sin_port= htons(se->s_port);
86     }
87
88     if (!inet_aton(copy,&su.sin.sin_addr)) {
89       struct hostent *he= gethostbyname(copy);
90       if (!he) { herror(copy); exit(4); }
91       if (he->h_addrtype != AF_INET ||
92           he->h_length != sizeof(su.sin.sin_addr) ||
93           !he->h_addrs[0] ||
94           he->h_addrs[1]) {
95         fprintf(stderr,"hostname lookup `%s' did not yield"
96                 " exactly one IPv4 address\n",copy);
97         exit(4);
98       }
99       memcpy(su.sin.sin_addr, he->h_addrs[0], sizeof(su.sin.sin_addr));
100     }
101   }
102
103   master= socket(su.sa.sa_family,SOCK_STREAM,0);
104   if (master<0) { perror("socket"); exit(8); }
105
106   
107   
108     if (
109
110       sdigit((unsigned char)bindname[0])) {
111     
112
113   if (argv[0]
114     
115   startup(argv);
116   writebuf_startup();
117   writebuf_mainloop();
118   exit(0);
119 }