Merge with git+ssh://pasky.or.cz/srv/git/elinks.git
[elinks.git] / src / protocol / common.c
blobd22fd84b1aff273a67c57bb8d444654656731ac0
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 enum 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. Do not use
69 * add_string_to_string, because it for some reason returns
70 * NULL if the second string is empty. */
71 if (!add_bytes_to_string(&decoded, dirpath.source, dirpath.length))
72 goto out_of_memory;
73 decode_uri_string(&decoded);
75 if (!local && !add_char_to_string(&location, '/'))
76 goto out_of_memory;
78 if (!add_to_string(page, "<html>\n<head><title>"))
79 goto out_of_memory;
81 if (!local && !add_html_to_string(page, location.source, location.length))
82 goto out_of_memory;
84 if (!add_html_to_string(page, decoded.source, decoded.length)
85 || !add_to_string(page, "</title>\n<base href=\"")
86 || !add_html_to_string(page, location.source, location.length)
87 || !add_html_to_string(page, dirpath.source, dirpath.length))
88 goto out_of_memory;
90 if (!add_to_string(page, "\" />\n</head>\n<body>\n<h2>"))
91 goto out_of_memory;
93 /* Use module names? */
94 switch (uri->protocol) {
95 case PROTOCOL_FILE:
96 info = "Local";
97 break;
98 case PROTOCOL_FSP:
99 info = "FSP";
100 break;
101 case PROTOCOL_FTP:
102 info = "FTP";
103 break;
104 case PROTOCOL_GOPHER:
105 info = "Gopher";
106 break;
107 case PROTOCOL_SMB:
108 info = "Samba";
109 break;
110 default:
111 info = "?";
114 if (!add_to_string(page, info)
115 || !add_to_string(page, " directory "))
116 goto out_of_memory;
118 if (!local && !add_string_to_string(page, &location))
119 goto out_of_memory;
121 /* Make the directory path with links to each subdir. */
123 const unsigned char *slash = dirpath.source;
124 const unsigned char *pslash = slash;
125 const unsigned char sep = local ? CHAR_DIR_SEP : '/';
127 while ((slash = strchr(slash, sep)) != NULL) {
128 done_string(&decoded);
129 if (!init_string(&decoded)
130 || !add_bytes_to_string(&decoded, pslash, slash - pslash))
131 goto out_of_memory;
132 decode_uri_string(&decoded);
134 if (!add_to_string(page, "<a href=\"")
135 || !add_html_to_string(page, location.source, location.length)
136 || !add_html_to_string(page, dirpath.source, slash + 1 - dirpath.source)
137 || !add_to_string(page, "\">")
138 || !add_html_to_string(page, decoded.source, decoded.length)
139 || !add_to_string(page, "</a>")
140 || !add_html_to_string(page, &sep, 1))
141 goto out_of_memory;
143 pslash = ++slash;
147 if (!add_to_string(page, "</h2>\n<pre>")) {
148 out_of_memory:
149 done_string(page);
152 done_string(&dirpath);
153 done_string(&decoded);
154 done_string(&location);
156 return page->length > 0 ? S_OK : S_OUT_OF_MEM;