]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.sbin/sysinstall/httpdirect.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / usr.sbin / sysinstall / httpdirect.c
1 /*
2  * Copyright (c) 1999
3  *      Philipp Mergenthaler <philipp.mergenthaler@stud.uni-karlsruhe.de>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29
30 #include "sysinstall.h"
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <sys/param.h>
35 #include <netdb.h>
36
37 extern const char *ftp_dirs[]; /* defined in ftp.c */
38
39 Boolean
40 mediaInitHTTPDirect(Device *dev)
41 {
42     bool found=FALSE;               /* end of header line */
43     char *rel, req[BUFSIZ];
44     int fdir;
45
46     /* 
47      * First verify basic access
48      */
49     checkAccess(TRUE, FALSE);
50     while (variable_get(VAR_HTTP_HOST) == NULL) {
51         if (DITEM_STATUS(mediaSetHTTPDirect(NULL)) == DITEM_FAILURE)
52             return FALSE;
53         checkAccess(TRUE, FALSE);
54     }
55 again:
56     /* If the release is specified as "__RELEASE" or "any", then just
57      * assume that the path the user gave is ok.
58      */
59     rel = variable_get(VAR_RELNAME);
60     /*
61     msgConfirm("rel: -%s-", rel);
62     */
63
64     if (strcmp(rel, "__RELEASE") && strcmp(rel, "any"))  {
65         for (fdir = 0; ftp_dirs[fdir]; fdir++) {
66             sprintf(req, "%s/%s/%s", variable_get(VAR_HTTP_DIR),
67                 ftp_dirs[fdir], rel);
68             variable_set2(VAR_HTTP_PATH, req, 0);
69             if (checkAccess(FALSE, FALSE)) {
70                 found = TRUE;
71                 break;
72             }
73         }
74     } else {
75         variable_set2(VAR_HTTP_PATH, variable_get(VAR_HTTP_DIR), 0);
76         found = checkAccess(FALSE, FALSE);
77     }
78     if (!found) {
79         msgConfirm("No such directory: %s\n"
80                    "please check the URL and try again.", variable_get(VAR_HTTP_PATH));
81         variable_unset(VAR_HTTP_PATH);
82         dialog_clear_norefresh();
83         clear();
84         if (DITEM_STATUS(mediaSetHTTPDirect(NULL)) != DITEM_FAILURE) goto again;
85     }
86     return found;
87 }
88
89 FILE *
90 mediaGetHTTPDirect(Device *dev, char *file, Boolean probe)
91 {
92     FILE *fp;
93     int rv, s, af;
94     bool el;                    /* end of header line */
95     char *cp, buf[PATH_MAX], req[BUFSIZ];
96     struct addrinfo hints, *res, *res0;
97
98     af = variable_cmp(VAR_IPV6_ENABLE, "YES") ? AF_INET : AF_UNSPEC;
99     memset(&hints, 0, sizeof(hints));
100     hints.ai_family = af;
101     hints.ai_socktype = SOCK_STREAM;
102     hints.ai_protocol = 0;
103     if ((rv = getaddrinfo(variable_get(VAR_HTTP_HOST),
104                           variable_get(VAR_HTTP_PORT), &hints, &res0)) != 0) {
105         msgConfirm("%s", gai_strerror(rv));
106         return NULL;
107     }
108     s = -1;
109     for (res = res0; res; res = res->ai_next) {
110         if ((s = socket(res->ai_family, res->ai_socktype,
111                         res->ai_protocol)) < 0)
112             continue;
113         if (connect(s, res->ai_addr, res->ai_addrlen) >= 0)
114             break;
115         close(s);
116         s = -1;
117     }
118     freeaddrinfo(res0);
119     if (s == -1) {
120         msgConfirm("Couldn't connect to http://%s:%s/",
121                     variable_get(VAR_HTTP_HOST),variable_get(VAR_HTTP_PORT));
122         return NULL;
123     }
124                                                    
125     sprintf(req,"GET /%s/%s HTTP/1.0\r\n\r\n",
126             variable_get(VAR_HTTP_PATH), file);
127
128     if (isDebug()) {
129         msgDebug("sending http request: %s\n",req);
130     }
131     write(s,req,strlen(req));
132
133 /*
134  *  scan the headers of the response
135  *  this is extremely quick'n dirty
136  *
137  */
138     cp=buf;
139     el=FALSE;
140     rv=read(s,cp,1);
141     while (rv>0) {
142         if ((*cp == '\012') && el) {
143             /* reached end of a header line */
144             if (!strncmp(buf,"HTTP",4)) {
145                 rv=strtol((char *)(buf+9),0,0);
146                 *(cp-1)='\0';           /* chop the CRLF off */
147                 if (probe && (rv != 200)) {
148                     return NULL;
149                 } else if (rv >= 500) {
150                     msgConfirm("Server error %s when sending %s, you could try an other server",buf, req);
151                     return NULL;
152                 } else if (rv == 404) {
153                     msgConfirm("%s was not found, maybe directory or release-version are wrong?",req);
154                     return NULL;
155                 } else if (rv >= 400) {
156                     msgConfirm("Client error %s, you could try an other server",buf);
157                     return NULL;
158                 } else if (rv >= 300) {
159                     msgConfirm("Error %s",buf);
160                     return NULL;
161                 } else if (rv != 200) {
162                     msgConfirm("Error %s when sending %s, you could try an other server",buf, req);
163                     return NULL;
164                 }
165             }
166             /* ignore other headers */
167             /* check for "\015\012" at beginning of line, i.e. end of headers */
168             if ((cp-buf) == 1) 
169                 break;
170             cp=buf;
171             rv=read(s,cp,1);
172         } else {
173             el=FALSE;
174             if (*cp == '\015')
175                 el=TRUE;
176             cp++;
177             rv=read(s,cp,1);
178         }
179     }
180     fp=fdopen(s,"r");
181     return fp;
182 }