help_view: one in all patch
[cmus.git] / server.c
blob17256d5a087eb558c16a113f38f54cceff92493f
1 /*
2 * Copyright 2004-2005 Timo Hirvonen
3 *
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
17 * 02111-1307, USA.
20 #include "server.h"
21 #include "prog.h"
22 #include "command_mode.h"
23 #include "debug.h"
25 #include <unistd.h>
26 #include <sys/un.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <errno.h>
30 #include <stdio.h>
31 #include <string.h>
33 static struct sockaddr_un addr;
34 static int remote_socket = -1;
36 #define MAX_CLIENTS 10
38 static void read_commands(int fd)
40 char buf[1024];
41 int pos = 0;
43 while (1) {
44 int rc, s;
46 rc = read(fd, buf + pos, sizeof(buf) - pos);
47 if (rc == -1) {
48 break;
50 if (rc == 0) {
51 break;
53 pos += rc;
55 s = 0;
56 while (1) {
57 int i;
59 for (i = s; i < pos; i++) {
60 if (buf[i] == '\n') {
61 buf[i] = 0;
62 run_command(buf + s);
63 s = i + 1;
64 break;
67 if (i == pos)
68 break;
70 memmove(buf, buf + s, pos - s);
71 pos -= s;
75 int remote_server_serve(void)
77 struct sockaddr saddr;
78 socklen_t saddr_size = sizeof(saddr);
79 int fd;
81 fd = accept(remote_socket, &saddr, &saddr_size);
82 if (fd == -1) {
83 return -1;
85 read_commands(fd);
86 close(fd);
87 return 0;
90 int remote_server_init(const char *address)
92 /* create socket - domain, type, protocol (IP) */
93 remote_socket = socket(PF_UNIX, SOCK_STREAM, 0);
94 if (remote_socket == -1)
95 die_errno("socket");
96 addr.sun_family = AF_UNIX;
97 strncpy(addr.sun_path, address, sizeof(addr.sun_path) - 1);
99 if (bind(remote_socket, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
100 int sock;
102 if (errno != EADDRINUSE)
103 die_errno("bind");
105 /* address already in use */
107 /* try to connect to server */
108 sock = socket(PF_UNIX, SOCK_STREAM, 0);
109 if (sock == -1)
110 die_errno("socket");
112 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
113 if (errno != ENOENT && errno != ECONNREFUSED)
114 die_errno("connect");
116 close(sock);
117 /* server not running => dead socket */
119 /* try to remove dead socket */
120 if (unlink(addr.sun_path) == -1 && errno != ENOENT)
121 die_errno("unlink");
122 if (bind(remote_socket, (struct sockaddr *)&addr, sizeof(addr)) == -1)
123 die_errno("bind");
124 } else {
125 /* server already running */
126 close(sock);
127 die("cmus is already listening on socket %s\n", address);
130 /* start listening */
131 BUG_ON(listen(remote_socket, MAX_CLIENTS) == -1);
132 return remote_socket;
135 void remote_server_exit(void)
137 close(remote_socket);
138 if (unlink(addr.sun_path) == -1)
139 d_print("unlink failed\n");