1 /* $NetBSD: main.c,v 1.22 2018/11/25 07:37:20 mrg Exp $ */ 2 3 /* $eterna: main.c,v 1.6 2011/11/18 09:21:15 mrg Exp $ */ 4 /* from: eterna: bozohttpd.c,v 1.159 2009/05/23 02:14:30 mrg Exp */ 5 6 /* 7 * Copyright (c) 1997-2018 Matthew R. Green 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer and 17 * dedication in the documentation and/or other materials provided 18 * with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 */ 33 34 /* this program is dedicated to the Great God of Processed Cheese */ 35 36 /* 37 * main.c: C front end to bozohttpd 38 */ 39 40 #include <sys/types.h> 41 #include <sys/param.h> 42 43 #include <errno.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <syslog.h> 47 #include <time.h> 48 #include <unistd.h> 49 50 #include "bozohttpd.h" 51 52 /* variables and functions */ 53 #ifndef LOG_FTP 54 #define LOG_FTP LOG_DAEMON 55 #endif 56 57 /* print a usage message, and then exit */ 58 BOZO_DEAD static void 59 usage(bozohttpd_t *httpd, char *progname) 60 { 61 bozowarn(httpd, "usage: %s [options] slashdir [virtualhostname]", 62 progname); 63 bozowarn(httpd, "options:"); 64 65 if (have_daemon_mode) 66 bozowarn(httpd, " -b\t\t\tbackground and go into daemon mode"); 67 if (have_cgibin && 68 have_dynamic_content) 69 bozowarn(httpd, " -C arg prog\t\tadd this CGI handler"); 70 if (have_cgibin) 71 bozowarn(httpd, " -c cgibin\t\tenable cgi-bin support in " 72 "this directory"); 73 if (have_debug) 74 bozowarn(httpd, " -d\t\t\tenable debug support"); 75 if (have_cgibin) 76 bozowarn(httpd, " -E\t\t\tenable CGI support for user dirs"); 77 if (have_user && 78 have_cgibin) 79 bozowarn(httpd, " -e\t\t\tdon't clean the environment " 80 "(-t and -U only)"); 81 if (have_daemon_mode) 82 bozowarn(httpd, " -f\t\t\tforeground in daemon mode"); 83 if (have_all) 84 bozowarn(httpd, " -G print version number and exit"); 85 if (have_dirindex) 86 bozowarn(httpd, " -H\t\t\thide files starting with a period " 87 "(.) in index mode"); 88 if (have_all) 89 bozowarn(httpd, " -I port\t\tbind or use on this port"); 90 if (have_daemon_mode) 91 bozowarn(httpd, " -i address\t\tbind on this address " 92 "(daemon mode only)"); 93 if (have_lua) 94 bozowarn(httpd, " -L arg script\tadd this Lua script"); 95 if (have_dynamic_content) 96 bozowarn(httpd, " -M arg t c c11\tadd this mime extenstion"); 97 if (have_daemon_mode) 98 bozowarn(httpd, " -P pidfile\t\tpid file path"); 99 if (have_user) 100 bozowarn(httpd, " -p dir\t\t\"public_html\" directory name"); 101 102 if (have_all) { 103 bozowarn(httpd, " -S version\t\tset server version string"); 104 bozowarn(httpd, " -s\t\t\talways log to stderr"); 105 bozowarn(httpd, " -T type timeout\tset `type' timeout"); 106 bozowarn(httpd, " -t dir\t\tchroot to `dir'"); 107 bozowarn(httpd, " -U username\t\tchange user to `user'"); 108 } 109 if (have_user) 110 bozowarn(httpd, " -u\t\t\tenable ~user/public_html support"); 111 112 if (have_all) { 113 bozowarn(httpd, " -V\t\t\tUnknown virtual hosts go to " 114 "`slashdir'"); 115 bozowarn(httpd, " -v virtualroot\tenable virtual host " 116 "support in this directory"); 117 } 118 119 if (have_dirindex) 120 bozowarn(httpd, " -X\t\t\tdirectory index support"); 121 if (have_all) 122 bozowarn(httpd, " -x index\t\tdefault \"index.html\" " 123 "file name"); 124 125 if (have_ssl) { 126 bozowarn(httpd, " -Z cert privkey\tspecify path to server " 127 "certificate and private key file\n" 128 "\t\t\tin pem format and enable bozohttpd in " 129 "SSL mode"); 130 bozowarn(httpd, " -z ciphers\t\tspecify SSL ciphers"); 131 } 132 133 bozoerr(httpd, 1, "%s failed to start", progname); 134 } 135 136 int 137 main(int argc, char **argv) 138 { 139 bozo_httpreq_t *request; 140 bozohttpd_t httpd; 141 bozoprefs_t prefs; 142 char *progname; 143 const char *val; 144 int c; 145 146 (void) memset(&httpd, 0x0, sizeof(httpd)); 147 (void) memset(&prefs, 0x0, sizeof(prefs)); 148 149 if ((progname = strrchr(argv[0], '/')) == NULL) 150 progname = argv[0]; 151 else 152 progname++; 153 154 openlog(progname, LOG_PID|LOG_NDELAY, LOG_FTP); 155 156 bozo_set_defaults(&httpd, &prefs); 157 158 /* 159 * -r option was removed, do not reuse it for a while 160 */ 161 162 while ((c = getopt(argc, argv, 163 "C:EGHI:L:M:P:S:T:U:VXZ:bc:defhi:np:st:uv:x:z:")) != -1) { 164 switch (c) { 165 166 case 'b': 167 if (!have_daemon_mode) 168 no_daemon_mode: 169 bozoerr(&httpd, 1, "Daemon mode not enabled"); 170 171 /* 172 * test suite support - undocumented 173 * background == 2 (aka, -b -b) means to 174 * only process 1 per kid 175 */ 176 val = bozo_get_pref(&prefs, "background") == NULL ? 177 "1" : "2"; 178 bozo_set_pref(&httpd, &prefs, "background", val); 179 break; 180 181 case 'c': 182 if (!have_cgibin) 183 bozoerr(&httpd, 1, "CGI not enabled"); 184 185 bozo_cgi_setbin(&httpd, optarg); 186 break; 187 188 case 'C': 189 if (!have_dynamic_content && !have_cgibin) 190 bozoerr(&httpd, 1, 191 "dynamic CGI handler support not enabled"); 192 193 /* make sure there's two arguments */ 194 if (argc - optind < 1) 195 usage(&httpd, progname); 196 bozo_add_content_map_cgi(&httpd, optarg, 197 argv[optind++]); 198 break; 199 200 case 'd': 201 if (!have_debug) 202 bozowarn(&httpd, "Debugging not enabled"); 203 httpd.debug++; 204 break; 205 206 case 'E': 207 if (have_user && 208 have_cgibin) 209 bozoerr(&httpd, 1, "CGI not enabled"); 210 211 bozo_set_pref(&httpd, &prefs, "enable user cgibin", 212 "true"); 213 break; 214 215 case 'e': 216 if (!have_daemon_mode) 217 goto no_daemon_mode; 218 219 bozo_set_pref(&httpd, &prefs, "dirty environment", 220 "true"); 221 break; 222 223 case 'f': 224 if (!have_daemon_mode) 225 goto no_daemon_mode; 226 227 bozo_set_pref(&httpd, &prefs, "foreground", "true"); 228 break; 229 230 case 'G': 231 { 232 char version[128]; 233 234 bozo_get_version(version, sizeof(version)); 235 printf("bozohttpd version %s\n", version); 236 } 237 return 0; 238 239 case 'H': 240 if (!have_dirindex) 241 no_dirindex_support: 242 bozoerr(&httpd, 1, 243 "directory indexing not enabled"); 244 245 bozo_set_pref(&httpd, &prefs, "hide dots", "true"); 246 break; 247 248 case 'I': 249 bozo_set_pref(&httpd, &prefs, "port number", optarg); 250 break; 251 252 case 'i': 253 if (!have_daemon_mode) 254 goto no_daemon_mode; 255 256 bozo_set_pref(&httpd, &prefs, "bind address", optarg); 257 break; 258 259 case 'L': 260 if (!have_lua) 261 bozoerr(&httpd, 1, "Lua support not enabled"); 262 263 /* make sure there's two argument */ 264 if (argc - optind < 1) 265 usage(&httpd, progname); 266 bozo_add_lua_map(&httpd, optarg, argv[optind]); 267 optind++; 268 break; 269 270 case 'M': 271 if (!have_dynamic_content) 272 bozoerr(&httpd, 1, 273 "dynamic mime content support not enabled"); 274 275 /* make sure there're four arguments */ 276 if (argc - optind < 3) 277 usage(&httpd, progname); 278 bozo_add_content_map_mime(&httpd, optarg, argv[optind], 279 argv[optind+1], argv[optind+2]); 280 optind += 3; 281 break; 282 283 case 'n': 284 bozo_set_pref(&httpd, &prefs, "numeric", "true"); 285 break; 286 287 case 'P': 288 if (!have_daemon_mode) 289 goto no_daemon_mode; 290 291 bozo_set_pref(&httpd, &prefs, "pid file", optarg); 292 break; 293 294 case 'p': 295 if (!have_user) 296 no_user_support: 297 bozoerr(&httpd, 1, "User support not enabled"); 298 299 bozo_set_pref(&httpd, &prefs, "public_html", optarg); 300 break; 301 302 case 'S': 303 bozo_set_pref(&httpd, &prefs, "server software", 304 optarg); 305 break; 306 307 case 's': 308 bozo_set_pref(&httpd, &prefs, "log to stderr", "true"); 309 break; 310 311 case 'T': 312 /* make sure there're two arguments */ 313 if (argc - optind < 1) 314 usage(&httpd, progname); 315 if (bozo_set_timeout(&httpd, &prefs, 316 optarg, argv[optind])) { 317 bozoerr(&httpd, 1, 318 "invalid type '%s'", optarg); 319 /* NOTREACHED */ 320 } 321 optind++; 322 break; 323 324 case 't': 325 bozo_set_pref(&httpd, &prefs, "chroot dir", optarg); 326 break; 327 328 case 'U': 329 bozo_set_pref(&httpd, &prefs, "username", optarg); 330 break; 331 332 case 'u': 333 if (!have_user) 334 goto no_user_support; 335 336 bozo_set_pref(&httpd, &prefs, "enable users", "true"); 337 break; 338 339 case 'V': 340 bozo_set_pref(&httpd, &prefs, "unknown slash", "true"); 341 break; 342 343 case 'v': 344 bozo_set_pref(&httpd, &prefs, "virtual base", optarg); 345 break; 346 347 case 'X': 348 if (!have_dirindex) 349 goto no_dirindex_support; 350 351 bozo_set_pref(&httpd, &prefs, "directory indexing", 352 "true"); 353 break; 354 355 case 'x': 356 bozo_set_pref(&httpd, &prefs, "index.html", optarg); 357 break; 358 359 case 'Z': 360 if (!have_ssl) 361 no_ssl: 362 bozoerr(&httpd, 1, "ssl support not enabled"); 363 364 /* make sure there's two arguments */ 365 if (argc - optind < 1) 366 usage(&httpd, progname); 367 bozo_ssl_set_opts(&httpd, optarg, argv[optind++]); 368 break; 369 370 case 'z': 371 if (!have_ssl) 372 goto no_ssl; 373 374 bozo_ssl_set_ciphers(&httpd, optarg); 375 break; 376 377 default: 378 usage(&httpd, progname); 379 /* NOTREACHED */ 380 } 381 } 382 383 argc -= optind; 384 argv += optind; 385 386 if (argc == 0 || argc > 2) { 387 usage(&httpd, progname); 388 } 389 390 /* virtual host, and root of tree to serve */ 391 bozo_setup(&httpd, &prefs, argv[1], argv[0]); 392 393 /* 394 * read and process the HTTP request. 395 */ 396 do { 397 if ((request = bozo_read_request(&httpd)) != NULL) { 398 bozo_process_request(request); 399 bozo_clean_request(request); 400 } 401 } while (httpd.background); 402 403 return (0); 404 } 405