[build] legacy files update
[platform/upstream/multipath-tools.git] / multipathd / uxlsnr.c
1 /*
2  * Original author : tridge@samba.org, January 2002
3  * 
4  * Copyright (c) 2005 Christophe Varoqui
5  * Copyright (c) 2005 Benjamin Marzinski, Redhat
6  */
7
8 /*
9  * A simple domain socket listener
10  */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <stdarg.h>
15 #include <fcntl.h>
16 #include <errno.h>
17 #include <sys/ioctl.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/un.h>
21 #include <sys/poll.h>
22
23 #include <memory.h>
24 #include <debug.h>
25 #include <vector.h>
26 #include <structs.h>
27 #include <uxsock.h>
28 #include <defaults.h>
29
30 #include "uxlsnr.h"
31
32 #define SLEEP_TIME 5000
33
34 struct client {
35         int fd;
36         struct client *next, *prev;
37 };
38
39 static struct client *clients;
40 static unsigned num_clients;
41
42 /*
43  * handle a new client joining
44  */
45 static void new_client(int ux_sock)
46 {
47         struct client *c;
48         struct sockaddr addr;
49         socklen_t len = sizeof(addr);
50         int fd;
51
52         fd = accept(ux_sock, &addr, &len);
53         
54         if (fd == -1)
55                 return;
56
57         /* put it in our linked list */
58         c = (struct client *)MALLOC(sizeof(*c));
59         memset(c, 0, sizeof(*c));
60         c->fd = fd;
61         c->next = clients;
62         if (c->next) c->next->prev = c;
63         clients = c;
64         num_clients++;
65 }
66
67 /*
68  * kill off a dead client
69  */
70 static void dead_client(struct client *c)
71 {
72         close(c->fd);
73         if (c->prev) c->prev->next = c->next;
74         if (c->next) c->next->prev = c->prev;
75         if (c == clients) clients = c->next;
76         FREE(c);
77         num_clients--;
78 }
79
80 void free_polls (void)
81 {
82         FREE(polls);
83 }
84
85 /*
86  * entry point
87  */
88 void * uxsock_listen(int (*uxsock_trigger)(char *, char **, int *, void *),
89                         void * trigger_data)
90 {
91         int ux_sock;
92         size_t len;
93         int rlen;
94         char *inbuf;
95         char *reply;
96
97         ux_sock = ux_socket_listen(DEFAULT_SOCKET);
98
99         if (ux_sock == -1) {
100                 condlog(0, "ux_socket_listen error");
101                 exit(1);
102         }
103
104         polls = (struct pollfd *)MALLOC(0);
105
106         while (1) {
107                 struct client *c;
108                 int i, poll_count;
109
110                 /* setup for a poll */
111                 polls = REALLOC(polls, (1+num_clients) * sizeof(*polls));
112                 polls[0].fd = ux_sock;
113                 polls[0].events = POLLIN;
114
115                 /* setup the clients */
116                 for (i=1, c = clients; c; i++, c = c->next) {
117                         polls[i].fd = c->fd;
118                         polls[i].events = POLLIN;
119                 }
120
121                 /* most of our life is spent in this call */
122                 poll_count = poll(polls, i, SLEEP_TIME);
123                 
124                 if (poll_count == -1) {
125                         if (errno == EINTR)
126                                 continue;
127
128                         /* something went badly wrong! */
129                         condlog(0, "poll");
130                         exit(1);
131                 }
132
133                 if (poll_count == 0)
134                         continue;
135
136                 /* see if a client wants to speak to us */
137                 for (i=1, c = clients; c; i++) {
138                         struct client *next = c->next;
139
140                         if (polls[i].revents & POLLIN) {
141                                 if (recv_packet(c->fd, &inbuf, &len) != 0) {
142                                         dead_client(c);
143                                 } else {
144                                         inbuf[len - 1] = 0;
145                                         condlog(4, "Got request [%s]", inbuf);
146                                         uxsock_trigger(inbuf, &reply, &rlen,
147                                                         trigger_data);
148
149                                         if (reply) {
150                                                 if (send_packet(c->fd, reply,
151                                                      rlen) != 0) {
152                                                         dead_client(c);
153                                                 }
154                                                 FREE(reply);
155                                                 reply = NULL;
156                                         }
157                                         FREE(inbuf);
158                                 }
159                         }
160                         c = next;
161                 }
162
163                 /* see if we got a new client */
164                 if (polls[0].revents & POLLIN) {
165                         new_client(ux_sock);
166                 }
167         }
168
169         return NULL;
170 }