4 * $DragonFly: src/sbin/rconfig/server.c,v 1.1 2004/06/18 02:46:46 dillon Exp $
9 static void server_connection(int fd);
10 static void service_packet_loop(int fd);
11 static void server_chld_exit(int signo);
20 * Listen on one or more UDP and TCP addresses, fork for each one.
22 signal(SIGCHLD, SIG_IGN);
23 for (tag = AddrBase; tag; tag = tag->next) {
24 struct sockaddr_in sain;
30 bzero(&sain, sizeof(sain));
31 if (tag->name == NULL) {
32 sain.sin_addr.s_addr = INADDR_ANY;
35 host = strdup(tag->name);
36 if (inet_aton(host, &sain.sin_addr) == 0) {
38 if ((hp = gethostbyname2(host, AF_INET)) == NULL) {
39 fprintf(stderr, "Unable to resolve %s\n", host);
42 bcopy(hp->h_addr_list[0], &sain.sin_addr, hp->h_length);
44 host = strdup(hp->h_name);
48 sain.sin_port = htons(257);
49 sain.sin_len = sizeof(sain);
50 sain.sin_family = AF_INET;
53 if ((lfd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
54 fprintf(stderr, "%s: socket: %s\n", host, strerror(errno));
57 setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
58 if (bind(lfd, (void *)&sain, sizeof(sain)) < 0) {
59 fprintf(stderr, "%s: bind: %s\n", host, strerror(errno));
62 if (listen(lfd, 20) < 0) {
63 fprintf(stderr, "%s: listen: %s\n", host, strerror(errno));
66 signal(SIGCHLD, server_chld_exit);
68 int slen = sizeof(sain);
69 fd = accept(lfd, (void *)&sain, &slen);
75 ++nconnects; /* XXX sigblock/sigsetmask */
78 server_connection(fd);
86 if ((lfd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC)) < 0) {
87 fprintf(stderr, "%s: socket: %s\n", host, strerror(errno));
90 if (bind(lfd, (void *)&sain, sizeof(sain)) < 0) {
91 fprintf(stderr, "%s: bind: %s\n", host, strerror(errno));
94 service_packet_loop(lfd);
98 while (wait(NULL) > 0 || errno != EINTR)
104 server_chld_exit(int signo)
106 while (wait3(NULL, WNOHANG, NULL) > 0)
112 server_connection(int fd)
121 fi = fdopen(fd, "r");
122 fo = fdopen(dup(fd), "w");
124 if (gethostname(buf, sizeof(buf)) == 0) {
125 fprintf(fo, "108 HELLO SERVER=%s\r\n", buf);
127 fprintf(fo, "108 HELLO\r\n", buf);
131 while (fgets(buf, sizeof(buf), fi) != NULL) {
133 cmd = parse_str(&scan, PAS_ALPHA);
135 fprintf(fo, "502 Illegal Command String\r\n");
136 } else if (strcasecmp(cmd, "VAR") == 0) {
137 fprintf(fo, "100 OK\r\n");
138 } else if (strcasecmp(cmd, "TAG") == 0) {
139 if ((name = parse_str(&scan, PAS_ALPHA|PAS_NUMERIC)) == NULL) {
140 fprintf(fo, "401 Illegal Tag\r\n");
144 asprintf(&path, "%s/%s.sh", TagDir, name);
145 if ((fp = fopen(path, "r")) == NULL) {
146 fprintf(fo, "402 '%s' Not Found\r\n", name);
155 fprintf(fo, "201 SIZE=%ld\r\n", bytes);
157 n = (bytes > sizeof(buf)) ? sizeof(buf) : bytes;
158 n = fread(buf, 1, n, fp);
163 if (fwrite(buf, 1, n, fo) != n) {
170 if (bytes > 0 && ferror(fo) == 0) {
171 bzero(buf, sizeof(buf));
173 n = (bytes > sizeof(buf)) ? sizeof(buf) : bytes;
174 if (fwrite(buf, 1, n, fo) != n)
179 fprintf(fo, "202 ERROR=%d\r\n", error);
183 } else if (strcasecmp(cmd, "IDLE") == 0) {
184 if ((name = parse_str(&scan, PAS_ANY)) == NULL) {
185 fprintf(fo, "401 Illegal String\r\n");
187 fprintf(fo, "109 %s\r\n", name);
189 } else if (strcasecmp(cmd, "QUIT") == 0) {
190 fprintf(fo, "409 Bye!\r\n");
193 fprintf(fo, "501 Unknown Command\r\n");
202 * UDP packet loop. For now just handle one request per packet. Note that
203 * since the protocol is designed to be used in a broadcast environment,
204 * we only respond when we have something to contribute.
208 service_packet_loop(int fd)
210 struct sockaddr_in sain;
220 sain_len = sizeof(sain);
221 n = recvfrom(fd, ibuf, sizeof(ibuf) - 1, 0, (void *)&sain, &sain_len);
230 cmd = parse_str(&scan, PAS_ALPHA);
233 } else if (strcasecmp(cmd, "TAG") == 0) {
234 if ((name = parse_str(&scan, PAS_ALPHA|PAS_NUMERIC)) != NULL) {
237 asprintf(&path, "%s/%s.sh", TagDir, name);
238 if (stat(path, &st) == 0) {
239 snprintf(obuf, sizeof(obuf), "101 TAG=%s\r\n", name);
246 sendto(fd, obuf, n, 0, (void *)&sain, sain_len);