File: | bin/lwan/main.c |
Warning: | line 294, column 5 Potential leak of memory pointed to by 'c.ssl.cert' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * lwan - simple web server | |||
3 | * Copyright (c) 2012 L. A. F. Pereira <l@tia.mat.br> | |||
4 | * | |||
5 | * This program is free software; you can redistribute it and/or | |||
6 | * modify it under the terms of the GNU General Public License | |||
7 | * as published by the Free Software Foundation; either version 2 | |||
8 | * of the License, or any later version. | |||
9 | * | |||
10 | * This program is distributed in the hope that it will be useful, | |||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
13 | * GNU General Public License for more details. | |||
14 | * | |||
15 | * You should have received a copy of the GNU General Public License | |||
16 | * along with this program; if not, write to the Free Software | |||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
18 | */ | |||
19 | ||||
20 | #define _GNU_SOURCE | |||
21 | #include <getopt.h> | |||
22 | #include <stdlib.h> | |||
23 | #include <unistd.h> | |||
24 | #include <limits.h> | |||
25 | ||||
26 | #include "lwan-private.h" | |||
27 | #include "lwan-mod-serve-files.h" | |||
28 | ||||
29 | enum args { | |||
30 | ARGS_FAILED, | |||
31 | ARGS_USE_CONFIG, | |||
32 | ARGS_SERVE_FILES | |||
33 | }; | |||
34 | ||||
35 | static void print_module_info(void) | |||
36 | { | |||
37 | const struct lwan_module_info *module; | |||
38 | ||||
39 | printf("Built-in modules:"); | |||
40 | LWAN_SECTION_FOREACH(lwan_module, module)for (module = ({ extern const typeof(*module) __start_lwan_module []; __start_lwan_module; }); module < ({ extern const typeof (*module) __stop_lwan_module[]; __stop_lwan_module; }); (module )++) { | |||
41 | printf(" %s", module->name); | |||
42 | } | |||
43 | printf(".\n"); | |||
44 | } | |||
45 | ||||
46 | static void | |||
47 | print_handler_info(void) | |||
48 | { | |||
49 | const struct lwan_handler_info *handler; | |||
50 | ||||
51 | printf("Built-in handlers:"); | |||
52 | LWAN_SECTION_FOREACH(lwan_handler, handler)for (handler = ({ extern const typeof(*handler) __start_lwan_handler []; __start_lwan_handler; }); handler < ({ extern const typeof (*handler) __stop_lwan_handler[]; __stop_lwan_handler; }); (handler )++) { | |||
53 | printf(" %s", handler->name); | |||
54 | } | |||
55 | printf(".\n"); | |||
56 | } | |||
57 | ||||
58 | static void | |||
59 | print_build_time_configuration(void) | |||
60 | { | |||
61 | printf("Build-time configuration:"); | |||
62 | #ifdef LWAN_HAVE_LUA | |||
63 | printf(" Lua"); | |||
64 | #endif | |||
65 | #ifdef LWAN_HAVE_BROTLI | |||
66 | printf(" Brotli"); | |||
67 | #endif | |||
68 | #ifdef LWAN_HAVE_ZSTD | |||
69 | printf(" zstd"); | |||
70 | #endif | |||
71 | #ifdef LWAN_HAVE_MBEDTLS | |||
72 | printf(" mbedTLS"); | |||
73 | #endif | |||
74 | #ifdef LWAN_HAVE_LIBUCONTEXT | |||
75 | printf(" libucontext"); | |||
76 | #endif | |||
77 | #ifdef LWAN_HAVE_EPOLL | |||
78 | printf(" epoll"); | |||
79 | #endif | |||
80 | #ifdef LWAN_HAVE_KQUEUE | |||
81 | printf(" kqueue"); | |||
82 | #endif | |||
83 | #ifdef LWAN_HAVE_SO_ATTACH_REUSEPORT_CBPF | |||
84 | printf(" sockopt-reuseport-CBPF"); | |||
85 | #endif | |||
86 | #ifdef LWAN_HAVE_SO_INCOMING_CPU | |||
87 | printf(" sockopt-reuseport-incoming-cpu"); | |||
88 | #endif | |||
89 | #ifdef LWAN_HAVE_VALGRIND | |||
90 | printf(" valgrind"); | |||
91 | #endif | |||
92 | #ifdef LWAN_HAVE_SYSLOG | |||
93 | printf(" syslog"); | |||
94 | #endif | |||
95 | #ifdef HAVE_PYTHON | |||
96 | printf(" python"); | |||
97 | #endif | |||
98 | printf(".\n"); | |||
99 | } | |||
100 | ||||
101 | static void | |||
102 | print_help(const char *argv0, const struct lwan_config *config) | |||
103 | { | |||
104 | char path_buf[PATH_MAX4096]; | |||
105 | char *current_dir = get_current_dir_name(); | |||
106 | const char *config_file = lwan_get_config_path(path_buf, sizeof(path_buf)); | |||
107 | ||||
108 | printf("Usage: %s [--root /path/to/root/dir] [--listen addr:port]\n", argv0); | |||
109 | printf(" [--config] [--user username] [--chroot] [--modules|--handlers]\n"); | |||
110 | printf("\n"); | |||
111 | printf("Serve files through HTTP.\n\n"); | |||
112 | printf("Options:\n"); | |||
113 | printf(" -r, --root Path to serve files from (default: ./wwwroot).\n"); | |||
114 | printf("\n"); | |||
115 | printf(" -l, --listen Listener (default: %s).\n", config->listener); | |||
116 | #ifdef LWAN_HAVE_MBEDTLS | |||
117 | printf(" -L, --tls-listen TLS Listener (default: %s).\n", | |||
118 | config->tls_listener ? | |||
119 | config->tls_listener : "not listening"); | |||
120 | #endif | |||
121 | printf("\n"); | |||
122 | printf(" -c, --config Path to config file path.\n"); | |||
123 | printf(" -u, --user Username to drop privileges to (root required).\n"); | |||
124 | printf(" -C, --chroot Chroot to path passed to --root (root required).\n"); | |||
125 | #ifdef LWAN_HAVE_MBEDTLS | |||
126 | printf("\n"); | |||
127 | printf(" -P, --cert-path Path to TLS certificate.\n"); | |||
128 | printf(" -K, --cert-key Path to TLS key.\n"); | |||
129 | #endif | |||
130 | printf("\n"); | |||
131 | printf(" -h, --help This.\n"); | |||
132 | printf("\n"); | |||
133 | printf("Examples:\n"); | |||
134 | printf(" Serve system-wide documentation:\n"); | |||
135 | printf(" %s -r /usr/share/doc\n", argv0); | |||
136 | printf(" Serve on a different port:\n"); | |||
137 | printf(" %s -l '*:1337'\n", argv0); | |||
138 | printf(" Use %s from %s:\n", config_file, current_dir); | |||
139 | printf(" %s\n", argv0); | |||
140 | printf(" Use /etc/%s:\n", config_file); | |||
141 | printf(" %s -c /etc/%s\n", argv0, config_file); | |||
142 | #ifdef LWAN_HAVE_MBEDTLS | |||
143 | printf(" Serve system docs with HTTP and HTTPS:\n"); | |||
144 | printf(" %s -P /path/to/cert.pem -K /path/to/cert.key \\\n" | |||
145 | " -l '*:8080' -L '*:8081' -r /usr/share/doc\n", argv0); | |||
146 | #endif | |||
147 | printf("\n"); | |||
148 | print_build_time_configuration(); | |||
149 | print_module_info(); | |||
150 | print_handler_info(); | |||
151 | printf("\n"); | |||
152 | printf("Report bugs at <https://github.com/lpereira/lwan>.\n"); | |||
153 | ||||
154 | free(current_dir); | |||
155 | } | |||
156 | ||||
157 | static enum args | |||
158 | parse_args(int argc, char *argv[], struct lwan_config *config, char *root, | |||
159 | struct lwan_straitjacket *sj) | |||
160 | { | |||
161 | static const struct option opts[] = { | |||
162 | { .name = "root", .has_arg = 1, .val = 'r' }, | |||
163 | { .name = "listen", .has_arg = 1, .val = 'l' }, | |||
164 | { .name = "help", .val = 'h' }, | |||
165 | { .name = "config", .has_arg = 1, .val = 'c' }, | |||
166 | { .name = "chroot", .val = 'C' }, | |||
167 | { .name = "user", .val = 'u', .has_arg = 1 }, | |||
168 | #ifdef LWAN_HAVE_MBEDTLS | |||
169 | { .name = "tls-listen", .val = 'L', .has_arg = 1 }, | |||
170 | { .name = "cert-path", .val = 'P', .has_arg = 1 }, | |||
171 | { .name = "cert-key", .val = 'K', .has_arg = 1 }, | |||
172 | #endif | |||
173 | { } | |||
174 | }; | |||
175 | int c, optidx = 0; | |||
176 | enum args result = ARGS_USE_CONFIG; | |||
177 | ||||
178 | while ((c = getopt_long(argc, argv, "L:P:K:hr:l:c:u:C", opts, &optidx)) != -1) { | |||
179 | switch (c) { | |||
180 | #ifdef LWAN_HAVE_MBEDTLS | |||
181 | case 'L': | |||
182 | free(config->tls_listener); | |||
183 | config->tls_listener = strdup(optarg); | |||
184 | result = ARGS_SERVE_FILES; | |||
185 | break; | |||
186 | ||||
187 | case 'P': | |||
188 | free(config->ssl.cert); | |||
189 | config->ssl.cert = strdup(optarg); | |||
190 | break; | |||
191 | ||||
192 | case 'K': | |||
193 | free(config->ssl.key); | |||
194 | config->ssl.key = strdup(optarg); | |||
195 | break; | |||
196 | #endif | |||
197 | case 'u': | |||
198 | free((char *)sj->user_name); | |||
199 | sj->user_name = (const char *)strdup(optarg); | |||
200 | break; | |||
201 | ||||
202 | case 'C': | |||
203 | sj->chroot_path = root; | |||
204 | break; | |||
205 | ||||
206 | case 'c': | |||
207 | free(config->config_file_path); | |||
208 | config->config_file_path = strdup(optarg); | |||
209 | result = ARGS_USE_CONFIG; | |||
210 | break; | |||
211 | ||||
212 | case 'l': | |||
213 | free(config->listener); | |||
214 | config->listener = strdup(optarg); | |||
215 | result = ARGS_SERVE_FILES; | |||
216 | break; | |||
217 | ||||
218 | case 'r': { | |||
219 | size_t len = strlen(optarg); | |||
220 | ||||
221 | if (len >= PATH_MAX4096) { | |||
222 | fprintf(stderrstderr, "Root path length exeeds %d characters\n", PATH_MAX4096); | |||
223 | return ARGS_FAILED; | |||
224 | } | |||
225 | ||||
226 | memcpy(root, optarg, len + 1); | |||
227 | result = ARGS_SERVE_FILES; | |||
228 | break; | |||
229 | } | |||
230 | ||||
231 | case 'h': | |||
232 | print_help(argv[0], config); | |||
233 | return ARGS_FAILED; | |||
234 | ||||
235 | default: | |||
236 | printf("Run %s --help for usage information.\n", argv[0]); | |||
237 | return ARGS_FAILED; | |||
238 | } | |||
239 | } | |||
240 | ||||
241 | return result; | |||
242 | } | |||
243 | ||||
244 | int | |||
245 | main(int argc, char *argv[]) | |||
246 | { | |||
247 | struct lwan l; | |||
248 | struct lwan_config c; | |||
249 | struct lwan_straitjacket sj = {}; | |||
250 | char root_buf[PATH_MAX4096]; | |||
251 | char *root = root_buf; | |||
252 | int ret = EXIT_SUCCESS0; | |||
253 | ||||
254 | if (!getcwd(root, PATH_MAX4096)) | |||
| ||||
255 | return 1; | |||
256 | ||||
257 | c = *lwan_get_default_config(); | |||
258 | c.listener = strdup("*:8080"); | |||
259 | ||||
260 | switch (parse_args(argc, argv, &c, root, &sj)) { | |||
261 | case ARGS_SERVE_FILES: | |||
262 | lwan_status_info("Serving files from %s", root)lwan_status_info_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/bin/lwan/main.c" , 262, __FUNCTION__, "Serving files from %s", root); | |||
263 | ||||
264 | if (sj.chroot_path) { | |||
265 | root = "/"; | |||
266 | } | |||
267 | lwan_straitjacket_enforce(&sj); | |||
268 | ||||
269 | lwan_init_with_config(&l, &c); | |||
270 | ||||
271 | const struct lwan_url_map map[] = { | |||
272 | { .prefix = "/", SERVE_FILES_SETTINGS(root, "index.html", true).module = lwan_module_info_serve_files.module, .args = ((struct lwan_serve_files_settings[]) {{ .read_ahead = (128 * 1024), . root_path = root, .index_html = "index.html", .serve_precompressed_files = 1, .directory_list_template = ((void*)0), .auto_index = 1, .auto_index_readme = 1, .cache_for = 5, }}), .flags = (enum lwan_handler_flags )0 }, | |||
273 | { } | |||
274 | }; | |||
275 | lwan_set_url_map(&l, map); | |||
276 | break; | |||
277 | case ARGS_USE_CONFIG: | |||
278 | lwan_straitjacket_enforce(&sj); | |||
279 | if (c.config_file_path) | |||
280 | lwan_init_with_config(&l, &c); | |||
281 | else | |||
282 | lwan_init(&l); | |||
283 | break; | |||
284 | case ARGS_FAILED: | |||
285 | ret = EXIT_FAILURE1; | |||
286 | goto out; | |||
287 | } | |||
288 | ||||
289 | lwan_main_loop(&l); | |||
290 | lwan_shutdown(&l); | |||
291 | ||||
292 | out: | |||
293 | free(c.listener); | |||
294 | free(c.config_file_path); | |||
| ||||
295 | free((char *)sj.user_name); | |||
296 | ||||
297 | return ret; | |||
298 | } |