4 * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved.
6 * This code is derived from software contributed to The DragonFly Project
7 * by Matthew Dillon <dillon@backplane.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
19 * 3. Neither the name of The DragonFly Project nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific, prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 static void udp_alarm(int signo);
45 return(c == ' ' || c == '\t' || c == '\r' || c == '\n');
49 parse_str(char **scanp, int flags)
54 for (base = *scanp; *base && iswhite(*base); ++base)
56 for (ptr = base; *ptr && !iswhite(*ptr); ++ptr) {
57 if (flags & PAS_ALPHA) {
58 if ((*ptr >= 'a' && *ptr <= 'z') ||
59 (*ptr >= 'A' && *ptr <= 'Z') ||
65 if (flags & PAS_NUMERIC) {
66 if (*ptr >= '0' && *ptr <= '9')
69 if ((flags & PAS_ANY) == 0)
79 udp_transact(struct sockaddr_in *sain, struct sockaddr_in *rsin, int *pfd,
80 char **bufp, int *lenp, const char *ctl, ...)
85 socklen_t rsin_len = sizeof(*rsin);
97 if ((fd = *pfd) < 0) {
98 struct sockaddr_in lsin;
100 lsin.sin_addr.s_addr = INADDR_ANY;
102 lsin.sin_family = AF_INET;
103 if ((fd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC)) < 0) {
104 asprintf(bufp, "udp_transaction: socket: %s", strerror(errno));
105 *lenp = strlen(*bufp);
108 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
109 if (bind(fd, (void *)&lsin, sizeof(lsin)) < 0) {
110 asprintf(bufp, "udp_transaction: bind: %s", strerror(errno));
111 *lenp = strlen(*bufp);
119 vsnprintf(buf, sizeof(buf), ctl, va);
121 if (sendto(fd, buf, strlen(buf), 0, (void *)sain, sizeof(*sain)) >= 0) {
122 struct sigaction nact;
123 struct sigaction oact;
125 bzero(&nact, sizeof(nact));
126 nact.sa_handler = udp_alarm;
128 sigaction(SIGALRM, &nact, &oact);
130 n = recvfrom(fd, buf, sizeof(buf) - 1, 0, (void *)rsin, &rsin_len);
132 sigaction(SIGALRM, &oact, NULL);
134 if (errno == EINTR && --nretry > 0)
136 asprintf(bufp, "udp_transaction: recvfrom: timeout");
137 *lenp = strlen(*bufp);
140 while (n > 0 && (buf[n - 1] == '\r' || buf[n - 1] == '\n'))
143 rc = strtol(buf, NULL, 10);
148 asprintf(bufp, "udp_transaction: sendto: %s", strerror(errno));
149 *lenp = strlen(*bufp);
155 tcp_transact(struct sockaddr_in *sain, FILE **pfi, FILE **pfo, char **bufp,
156 int *lenp, const char *ctl, ...)
170 if ((fd = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
171 asprintf(bufp, "tcp_transaction: socket: %s", strerror(errno));
172 *lenp = strlen(*bufp);
175 if (connect(fd, (void *)sain, sizeof(*sain)) < 0) {
176 asprintf(bufp, "tcp_transaction: connect: %s", strerror(errno));
177 *lenp = strlen(*bufp);
181 *pfi = fdopen(fd, "r");
182 *pfo = fdopen(dup(fd), "w");
183 if (tcp_transact(sain, pfi, pfo, bufp, lenp, NULL) != 108) {
189 asprintf(bufp, "tcp_transaction: did not get HELLO from server\n");
190 *lenp = strlen(*bufp);
194 printf("%s\n", *bufp);
201 vfprintf(*pfo, ctl, va);
205 if (fgets(buf, sizeof(buf), *pfi) != NULL) {
206 rc = strtol(buf, NULL, 10);
208 if (rc == 201 && strstr(buf, "SIZE=") != NULL) {
209 *lenp = strtol(strstr(buf, "SIZE=") + 5, NULL, 0);
211 *bufp = malloc(*lenp);
212 for (rc = 0; *bufp && rc < *lenp; rc += n) {
213 if ((n = *lenp - rc) > (int)sizeof(buf))
215 n = fread(*bufp + rc, 1, n, *pfi);
219 if (rc == *lenp && fgets(buf, sizeof(buf), *pfi)) {
220 if (strstr(buf, "ERROR=")) {
221 rc = strtol(strstr(buf, "ERROR=") + 6, NULL, 0);
234 asprintf(bufp, "tcp_transaction: download failed\n");
235 *lenp = strlen(*bufp);
238 while (n > 0 && (buf[n-1] == '\r' || buf[n-1] == '\n'))
245 asprintf(bufp, "tcp_transaction: read: %s", strerror(errno));
246 *lenp = strlen(*bufp);
257 udp_alarm(int signo __unused)