Bug 1013: Don't assume errno is between 0 and 100000
[elinks.git] / src / protocol / common.c
blobebf980829ab87032eb12d2111f31d2431ba212cb
1 /* Shared protocol functions */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #ifdef HAVE_SYS_TIME_H
8 #include <sys/time.h> /* FreeBSD needs this before resource.h */
9 #endif
10 #include <sys/types.h> /* FreeBSD needs this before resource.h */
11 #ifdef HAVE_SYS_RESOURCE_H
12 #include <sys/resource.h>
13 #endif
14 #ifdef HAVE_UNISTD_H
15 #include <unistd.h>
16 #endif
18 #include "elinks.h"
20 #include "config/options.h"
21 #include "osdep/osdep.h"
22 #include "protocol/common.h"
23 #include "protocol/protocol.h"
24 #include "protocol/uri.h"
25 #include "util/conv.h"
26 #include "util/memory.h"
27 #include "util/string.h"
30 /* Close all non-terminal file descriptors. */
31 void
32 close_all_non_term_fd(void)
34 int n;
35 int max = 1024;
36 #ifdef RLIMIT_NOFILE
37 struct rlimit lim;
39 if (!getrlimit(RLIMIT_NOFILE, &lim))
40 max = lim.rlim_max;
41 #endif
42 for (n = 3; n < max; n++)
43 close(n);
46 struct connection_state
47 init_directory_listing(struct string *page, struct uri *uri)
49 struct string dirpath = NULL_STRING;
50 struct string decoded = NULL_STRING;
51 struct string location = NULL_STRING;
52 unsigned char *info;
53 int local = (uri->protocol == PROTOCOL_FILE);
55 if (!init_string(page)
56 || !init_string(&dirpath)
57 || !init_string(&decoded)
58 || !init_string(&location)
59 || !add_uri_to_string(&dirpath, uri, URI_DATA)
60 || !add_uri_to_string(&location, uri, URI_DIR_LOCATION))
61 goto out_of_memory;
63 if (dirpath.length > 0
64 && !dir_sep(dirpath.source[dirpath.length - 1])
65 && !add_char_to_string(&dirpath, local ? CHAR_DIR_SEP : '/'))
66 goto out_of_memory;
68 /* Decode uri for displaying. */
69 if (!add_string_to_string(&decoded, &dirpath))
70 goto out_of_memory;
71 decode_uri_string(&decoded);
73 if (!local && !add_char_to_string(&location, '/'))
74 goto out_of_memory;
76 if (!add_to_string(page, "<html>\n<head><title>"))
77 goto out_of_memory;
79 if (!local && !add_html_to_string(page, location.source, location.length))
80 goto out_of_memory;
82 if (!add_html_to_string(page, decoded.source, decoded.length)
83 || !add_to_string(page, "</title>\n<base href=\"")
84 || !add_html_to_string(page, location.source, location.length)
85 || !add_html_to_string(page, dirpath.source, dirpath.length))
86 goto out_of_memory;
88 if (!add_to_string(page, "\" />\n</head>\n<body>\n<h2>"))
89 goto out_of_memory;
91 /* Use module names? */
92 switch (uri->protocol) {
93 case PROTOCOL_FILE:
94 info = "Local";
95 break;
96 case PROTOCOL_FSP:
97 info = "FSP";
98 break;
99 case PROTOCOL_FTP:
100 info = "FTP";
101 break;
102 case PROTOCOL_GOPHER:
103 info = "Gopher";
104 break;
105 case PROTOCOL_SMB:
106 info = "Samba";
107 break;
108 default:
109 info = "?";
112 if (!add_to_string(page, info)
113 || !add_to_string(page, " directory "))
114 goto out_of_memory;
116 if (!local && !add_string_to_string(page, &location))
117 goto out_of_memory;
119 /* Make the directory path with links to each subdir. */
121 const unsigned char *slash = dirpath.source;
122 const unsigned char *pslash = slash;
123 const unsigned char sep = local ? CHAR_DIR_SEP : '/';
125 while ((slash = strchr(slash, sep)) != NULL) {
126 done_string(&decoded);
127 if (!init_string(&decoded)
128 || !add_bytes_to_string(&decoded, pslash, slash - pslash))
129 goto out_of_memory;
130 decode_uri_string(&decoded);
132 if (!add_to_string(page, "<a href=\"")
133 || !add_html_to_string(page, location.source, location.length)
134 || !add_html_to_string(page, dirpath.source, slash + 1 - dirpath.source)
135 || !add_to_string(page, "\">")
136 || !add_html_to_string(page, decoded.source, decoded.length)
137 || !add_to_string(page, "</a>")
138 || !add_html_to_string(page, &sep, 1))
139 goto out_of_memory;
141 pslash = ++slash;
145 if (!add_to_string(page, "</h2>\n<pre>")) {
146 out_of_memory:
147 done_string(page);
150 done_string(&dirpath);
151 done_string(&decoded);
152 done_string(&location);
154 return page->length > 0
155 ? connection_state(S_OK)
156 : connection_state(S_OUT_OF_MEM);