2 * Copyright 2004-2005 Timo Hirvonen
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 #include "command_mode.h"
25 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
40 struct sockaddr_un un
;
41 struct sockaddr_in in
;
44 #define MAX_CLIENTS 10
46 static void read_commands(int fd
)
54 rc
= read(fd
, buf
+ pos
, sizeof(buf
) - pos
);
67 for (i
= s
; i
< pos
; i
++) {
78 memmove(buf
, buf
+ s
, pos
- s
);
83 int server_serve(void)
85 struct sockaddr saddr
;
86 socklen_t saddr_size
= sizeof(saddr
);
89 fd
= accept(server_socket
, &saddr
, &saddr_size
);
98 static void gethostbyname_failed(void)
100 const char *error
= "Unknown error.";
105 error
= "Host not found.";
108 error
= "A non-recoverable name server error.";
111 error
= "A temporary error occurred on an authoritative name server.";
114 die("gethostbyname: %s\n", error
);
117 void server_init(char *address
)
122 if (strchr(address
, '/')) {
123 addr
.sa
.sa_family
= AF_UNIX
;
124 strncpy(addr
.un
.sun_path
, address
, sizeof(addr
.un
.sun_path
) - 1);
126 addrlen
= sizeof(struct sockaddr_un
);
128 char *s
= strchr(address
, ':');
129 struct hostent
*hent
;
135 hent
= gethostbyname(address
);
137 gethostbyname_failed();
139 addr
.sa
.sa_family
= hent
->h_addrtype
;
140 switch (addr
.sa
.sa_family
) {
142 memcpy(&addr
.in
.sin_addr
, hent
->h_addr_list
[0], hent
->h_length
);
143 addr
.in
.sin_port
= htons(port
);
145 addrlen
= sizeof(addr
.in
);
148 die("unsupported address type\n");
152 server_socket
= socket(addr
.sa
.sa_family
, SOCK_STREAM
, 0);
153 if (server_socket
== -1)
156 if (bind(server_socket
, &addr
.sa
, addrlen
) == -1) {
159 if (errno
!= EADDRINUSE
)
162 /* address already in use */
163 if (addr
.sa
.sa_family
!= AF_UNIX
)
164 die("cmus is already listening on %s:%d\n", address
, port
);
166 /* try to connect to server */
167 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
171 if (connect(sock
, &addr
.sa
, addrlen
) == -1) {
172 if (errno
!= ENOENT
&& errno
!= ECONNREFUSED
)
173 die_errno("connect");
175 /* server not running => dead socket */
177 /* try to remove dead socket */
178 if (unlink(addr
.un
.sun_path
) == -1 && errno
!= ENOENT
)
180 if (bind(server_socket
, &addr
.sa
, addrlen
) == -1)
183 /* server already running */
184 die("cmus is already listening on socket %s\n", address
);
189 if (listen(server_socket
, MAX_CLIENTS
) == -1)
193 void server_exit(void)
195 close(server_socket
);
196 if (addr
.sa
.sa_family
== AF_UNIX
)
197 unlink(addr
.un
.sun_path
);