48 #include <sys/types.h> 58 EST_Regex RxURL(
"\\([a-z]+\\)://?\\([^/:]+\\)\\(:\\([0-9]+\\)\\)?\\(.*\\)");
60 static EST_Regex ipnum(
"[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+");
65 #define MAX_LINE_LENGTH (256) 67 static int port_to_int(
const char *port)
71 if (!port || *port ==
'\0')
74 if ((serv=getservbyname(port,
"tcp")))
95 path = url.
after(
"file:");
98 else if (!url.
matches(
RxURL, 0, start_of_bracket, end_of_bracket))
101 protocol = url.
at(start_of_bracket[1], end_of_bracket[1]-start_of_bracket[1]);
102 host = url.
at(start_of_bracket[2], end_of_bracket[2]-start_of_bracket[2]);
103 port = url.
at(start_of_bracket[4], end_of_bracket[4]-start_of_bracket[4]);
104 bitpath = url.
at(start_of_bracket[5], end_of_bracket[5]-start_of_bracket[5]);
106 if (protocol ==
"http")
107 path = protocol +
"://" + host + bitpath;
114 static int connect_to_server(
const char *host,
int port)
116 struct sockaddr_in address;
117 struct hostent *hostentp;
121 memset(&address, 0,
sizeof(address));
125 address.sin_addr.s_addr = inet_addr(host);
126 address.sin_family = AF_INET;
128 else if ((hostentp=gethostbyname(host))==
NULL)
129 err(
"can't find host", host);
132 memset(&(address.sin_addr),0,
sizeof(
struct in_addr));
133 address.sin_family=hostentp->h_addrtype;
134 memmove(&address.sin_addr,
135 (hostentp->h_addr_list)[0],
138 address.sin_port=htons(port);
140 if ((s=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
141 err(
"can't create socket",
NIL);
143 if (connect(s, (
struct sockaddr *)&address,
sizeof(address)) < 0)
146 err(
"can't connect to host",
147 inet_ntoa(address.sin_addr));
153 static void server_send(
int s,
const char *text)
159 if ((sent = write(s, text, n))<0)
160 err(
"error talking to server",
NIL);
165 static const char *server_get_line(
int s)
174 if ((n=read(s, p, 1)) == 0)
177 err(
"error while reading from server",
NIL);
178 else if (*(p++) ==
'\n')
195 if (r_or_w[0] ==
'r')
197 else if (r_or_w[0] ==
'w')
200 err(
"mode not understood for -", r_or_w);
215 if (strcmp(name,
"-")==0)
218 if (r_or_w[0] ==
'r')
219 if (r_or_w[1] ==
'+' || r_or_w[1] ==
'w')
220 mode = O_RDWR|O_CREAT;
223 else if (r_or_w[0] ==
'w')
224 if (r_or_w[1] ==
'+')
225 mode = O_RDWR|O_CREAT|O_TRUNC;
227 mode = O_WRONLY|O_CREAT|O_TRUNC;
228 else if (r_or_w[0] ==
'a')
229 if (r_or_w[1] ==
'+')
230 go_to_end = mode = O_RDWR;
232 go_to_end = mode = O_WRONLY|O_CREAT;
234 err(
"mode not understood", r_or_w);
239 fd=
open(name, mode, 0666);
241 if (fd >=0 && go_to_end)
257 if ((s=connect_to_server(host, port)) < 0)
265 char location[1024] =
"";
267 server_send(s,
"GET ");
268 server_send(s, path);
269 server_send(s,
" HTTP/1.0\n\n");
272 line= server_get_line(s);
274 if (sscanf(line,
"HTTP/%f %d", &http_version, &code) != 2)
277 err(
"HTTP error", line);
281 while((line = server_get_line(s)))
283 if (*line==
'\r' || *line ==
'\n' || *line ==
'\0')
285 else if (sscanf(line,
"Location: %s", location) == 1)
287 cout <<
"redirect to '" << location <<
"'\n";
291 if (code == 301 || code == 302)
295 if (*location ==
'\0')
296 err(
"Redirection to no loction",
NIL);
301 if (!
parse_url(location, sprotocol, shost, sport, spath))
302 err(
"redirection to bad URL", location);
304 s =
fd_open_url(sprotocol, shost, sport, spath,
"rb");
308 else if (*r_or_w ==
'w')
309 err(
"Write to HTTP url not yet implemented",
NIL);
337 if ((s=connect_to_server(host, port)) < 0)
340 server_send(s, text);
344 else if (*r_or_w ==
'w')
361 if (strcmp(protocol,
"file") == 0
362 && (!host || *host ==
'\0')
363 && (!port || *port ==
'\0'))
365 else if (strcmp(protocol,
"file") == 0 || strcmp(protocol,
"ftp") == 0)
366 return fd_open_ftp(host, port_to_int(port), path, r_or_w);
367 else if (strcmp(protocol,
"http") == 0)
368 return fd_open_http(host, port_to_int(port), path, r_or_w);
369 else if (strcmp(protocol,
"tcp") == 0)
370 return fd_open_tcp(host, port_to_int(port), path, r_or_w);
EST_Regex RxFILEURL("file:.*")
const int default_http_port
A Regular expression class to go with the CSTR EST_String class.
int fd_open_tcp(const char *host, int port, const char *text, const char *r_or_w)
#define EST_Regex_max_subexpressions
int fd_open_url(const char *protocol, const char *host, const char *port, const char *path, const char *r_or_w)
void err(const char *message, LISP x) EST_NORETURN
int fd_open_file(const char *name, const char *r_or_w)
const int default_ftp_port
EST_Regex RxURL("\\([a-z]+\\)://?\\([^/:]+\\)\\(:\\([0-9]+\\)\\)?\\(.*\\)")
int matches(const char *e, ssize_t pos=0) const
Exactly match this string?
FILE16 *(* open)(const char *, const char *, int, const char *, const char *)
int fd_open_stdinout(const char *r_or_w)
EST_String after(int pos, int len=1) const
Part after pos+len.
int fd_open_ftp(const char *host, int port, const char *path, const char *r_or_w)
EST_String at(int from, int len=0) const
Return part at position.
int fd_open_http(const char *host, int port, const char *path, const char *r_or_w)
int parse_url(const EST_String &url, EST_String &protocol, EST_String &host, EST_String &port, EST_String &path)