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"
27 #include <sys/types.h>
28 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
42 struct sockaddr_un un
;
43 struct sockaddr_in in
;
46 #define MAX_CLIENTS 10
48 static void read_commands(int fd
)
52 int authenticated
= addr
.sa
.sa_family
== AF_UNIX
;
57 rc
= read(fd
, buf
+ pos
, sizeof(buf
) - pos
);
67 for (i
= 0; i
< pos
; i
++) {
78 if (!server_password
) {
79 d_print("password is unset, tcp/ip disabled\n");
82 authenticated
= !strcmp(line
, server_password
);
84 d_print("authentication failed\n");
91 memmove(buf
, buf
+ s
, pos
- s
);
96 int server_serve(void)
98 struct sockaddr saddr
;
99 socklen_t saddr_size
= sizeof(saddr
);
102 fd
= accept(server_socket
, &saddr
, &saddr_size
);
107 /* unix connection is secure, other insecure */
108 run_only_safe_commands
= addr
.sa
.sa_family
!= AF_UNIX
;
110 run_only_safe_commands
= 0;
116 static void gethostbyname_failed(void)
118 const char *error
= "Unknown error.";
123 error
= "Host not found.";
126 error
= "A non-recoverable name server error.";
129 error
= "A temporary error occurred on an authoritative name server.";
132 die("gethostbyname: %s\n", error
);
135 void server_init(char *address
)
137 int port
= DEFAULT_PORT
;
140 if (strchr(address
, '/')) {
141 addr
.sa
.sa_family
= AF_UNIX
;
142 strncpy(addr
.un
.sun_path
, address
, sizeof(addr
.un
.sun_path
) - 1);
144 addrlen
= sizeof(struct sockaddr_un
);
146 char *s
= strchr(address
, ':');
147 struct hostent
*hent
;
153 hent
= gethostbyname(address
);
155 gethostbyname_failed();
157 addr
.sa
.sa_family
= hent
->h_addrtype
;
158 switch (addr
.sa
.sa_family
) {
160 memcpy(&addr
.in
.sin_addr
, hent
->h_addr_list
[0], hent
->h_length
);
161 addr
.in
.sin_port
= htons(port
);
163 addrlen
= sizeof(addr
.in
);
166 die("unsupported address type\n");
170 server_socket
= socket(addr
.sa
.sa_family
, SOCK_STREAM
, 0);
171 if (server_socket
== -1)
174 if (bind(server_socket
, &addr
.sa
, addrlen
) == -1) {
177 if (errno
!= EADDRINUSE
)
180 /* address already in use */
181 if (addr
.sa
.sa_family
!= AF_UNIX
)
182 die("cmus is already listening on %s:%d\n", address
, port
);
184 /* try to connect to server */
185 sock
= socket(AF_UNIX
, SOCK_STREAM
, 0);
189 if (connect(sock
, &addr
.sa
, addrlen
) == -1) {
190 if (errno
!= ENOENT
&& errno
!= ECONNREFUSED
)
191 die_errno("connect");
193 /* server not running => dead socket */
195 /* try to remove dead socket */
196 if (unlink(addr
.un
.sun_path
) == -1 && errno
!= ENOENT
)
198 if (bind(server_socket
, &addr
.sa
, addrlen
) == -1)
201 /* server already running */
202 die("cmus is already listening on socket %s\n", address
);
207 if (listen(server_socket
, MAX_CLIENTS
) == -1)
211 void server_exit(void)
213 close(server_socket
);
214 if (addr
.sa
.sa_family
== AF_UNIX
)
215 unlink(addr
.un
.sun_path
);