diff options
Diffstat (limited to 'src/tinyproxy.c')
-rw-r--r-- | src/tinyproxy.c | 547 |
1 files changed, 272 insertions, 275 deletions
diff --git a/src/tinyproxy.c b/src/tinyproxy.c index d1f8777..1d4cff0 100644 --- a/src/tinyproxy.c +++ b/src/tinyproxy.c @@ -1,4 +1,4 @@ -/* $Id: tinyproxy.c,v 1.51 2005-07-12 17:39:44 rjkaes Exp $ +/* $Id: tinyproxy.c,v 1.52 2005-08-15 03:54:31 rjkaes Exp $ * * The initialize routine. Basically sets up all the initial stuff (logfile, * listening socket, config options, etc.) and then sits there and loops @@ -44,8 +44,8 @@ RETSIGTYPE takesig(int sig); */ struct config_s config; float load = 0.00; -unsigned int received_sighup = FALSE; /* boolean */ -unsigned int processed_config_file = FALSE; /* boolean */ +unsigned int received_sighup = FALSE; /* boolean */ +unsigned int processed_config_file = FALSE; /* boolean */ /* * Handle a signal @@ -53,25 +53,24 @@ unsigned int processed_config_file = FALSE; /* boolean */ RETSIGTYPE takesig(int sig) { - pid_t pid; - int status; + pid_t pid; + int status; - switch (sig) { - case SIGHUP: - received_sighup = TRUE; - break; + switch (sig) { + case SIGHUP: + received_sighup = TRUE; + break; - case SIGTERM: - config.quit = TRUE; - break; + case SIGTERM: + config.quit = TRUE; + break; - case SIGCHLD: - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) - ; - break; - } + case SIGCHLD: + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) ; + break; + } - return; + return; } /* @@ -80,7 +79,7 @@ takesig(int sig) static void display_version(void) { - printf("%s %s (%s)\n", PACKAGE, VERSION, TARGET_SYSTEM); + printf("%s %s (%s)\n", PACKAGE, VERSION, TARGET_SYSTEM); } /* @@ -89,9 +88,9 @@ display_version(void) static void display_license(void) { - display_version(); + display_version(); - printf("\ + printf("\ Copyright 1998 Steven Young (sdyoung@well.com)\n\ Copyright 1998-2002 Robert James Kaes (rjkaes@users.sourceforge.net)\n\ Copyright 1999 George Talusan (gstalusan@uwaterloo.ca)\n\ @@ -118,8 +117,8 @@ display_license(void) static void display_usage(void) { - printf("Usage: %s [options]\n", PACKAGE); - printf("\ + printf("Usage: %s [options]\n", PACKAGE); + printf("\ Options:\n\ -d Operate in DEBUG mode.\n\ -c FILE Use an alternate configuration file.\n\ @@ -127,97 +126,97 @@ Options:\n\ -l Display the license.\n\ -v Display the version number.\n"); - /* Display the modes compiled into tinyproxy */ - printf("\nFeatures compiled in:\n"); + /* Display the modes compiled into tinyproxy */ + printf("\nFeatures compiled in:\n"); #ifdef XTINYPROXY_ENABLE - printf(" XTinyproxy header\n"); -#endif /* XTINYPROXY */ + printf(" XTinyproxy header\n"); +#endif /* XTINYPROXY */ #ifdef FILTER_ENABLE - printf(" Filtering\n"); -#endif /* FILTER_ENABLE */ + printf(" Filtering\n"); +#endif /* FILTER_ENABLE */ #ifndef NDEBUG - printf(" Debugging code\n"); -#endif /* NDEBUG */ + printf(" Debugging code\n"); +#endif /* NDEBUG */ #ifdef TRANSPARENT_PROXY - printf(" Transparent proxy support\n"); + printf(" Transparent proxy support\n"); #endif /* TRANSPARENT_PROXY */ #ifdef REVERSE_SUPPORT - printf(" Reverse proxy support\n"); -#endif /* REVERSE_SUPPORT */ + printf(" Reverse proxy support\n"); +#endif /* REVERSE_SUPPORT */ } int main(int argc, char **argv) { - int optch; - unsigned int godaemon = TRUE; /* boolean */ - struct passwd *thisuser = NULL; - struct group *thisgroup = NULL; - FILE* config_file; - - /* - * Disable the creation of CORE files right up front. - */ + int optch; + unsigned int godaemon = TRUE; /* boolean */ + struct passwd *thisuser = NULL; + struct group *thisgroup = NULL; + FILE *config_file; + + /* + * Disable the creation of CORE files right up front. + */ #if defined(HAVE_SETRLIMIT) && defined(NDEBUG) - struct rlimit core_limit = { 0, 0 }; - if (setrlimit(RLIMIT_CORE, &core_limit) < 0) { - fprintf(stderr, "%s: Could not set the core limit to zero.\n", - argv[0]); - exit(EX_SOFTWARE); - } -#endif /* HAVE_SETRLIMIT */ - - /* Default configuration file location */ - config.config_file = DEFAULT_CONF_FILE; - - /* - * Process the various options - */ - while ((optch = getopt(argc, argv, "c:vldh")) != EOF) { - switch (optch) { - case 'v': - display_version(); - exit(EX_OK); - case 'l': - display_license(); - exit(EX_OK); - case 'd': - godaemon = FALSE; - break; - case 'c': - config.config_file = safestrdup(optarg); - if (!config.config_file) { - fprintf(stderr, - "%s: Could not allocate memory.\n", - argv[0]); - exit(EX_SOFTWARE); - } - break; - case 'h': - default: - display_usage(); - exit(EX_OK); - } - } - - log_message(LOG_INFO, "Initializing " PACKAGE " ..."); - - /* - * Make sure the HTML error pages array is NULL to begin with. - * (FIXME: Should have a better API for all this) - */ - config.errorpages = NULL; - - /* - * Read in the settings from the config file. - */ + struct rlimit core_limit = { 0, 0 }; + if (setrlimit(RLIMIT_CORE, &core_limit) < 0) { + fprintf(stderr, "%s: Could not set the core limit to zero.\n", + argv[0]); + exit(EX_SOFTWARE); + } +#endif /* HAVE_SETRLIMIT */ + + /* Default configuration file location */ + config.config_file = DEFAULT_CONF_FILE; + + /* + * Process the various options + */ + while ((optch = getopt(argc, argv, "c:vldh")) != EOF) { + switch (optch) { + case 'v': + display_version(); + exit(EX_OK); + case 'l': + display_license(); + exit(EX_OK); + case 'd': + godaemon = FALSE; + break; + case 'c': + config.config_file = safestrdup(optarg); + if (!config.config_file) { + fprintf(stderr, + "%s: Could not allocate memory.\n", + argv[0]); + exit(EX_SOFTWARE); + } + break; + case 'h': + default: + display_usage(); + exit(EX_OK); + } + } + + log_message(LOG_INFO, "Initializing " PACKAGE " ..."); + + /* + * Make sure the HTML error pages array is NULL to begin with. + * (FIXME: Should have a better API for all this) + */ + config.errorpages = NULL; + + /* + * Read in the settings from the config file. + */ config_file = fopen(config.config_file, "r"); if (!config_file) { - fprintf(stderr, - "%s: Could not open configuration file \"%s\".\n", - argv[0], config.config_file); - exit(EX_SOFTWARE); - } + fprintf(stderr, + "%s: Could not open configuration file \"%s\".\n", + argv[0], config.config_file); + exit(EX_SOFTWARE); + } if (config_compile() || config_parse(&config, config_file)) { fprintf(stderr, "Unable to parse configuration file. Not starting.\n"); @@ -232,194 +231,192 @@ main(int argc, char **argv) if (config.logf_name) { if (open_log_file(config.logf_name) < 0) { fprintf(stderr, - "%s: Could not create log file.\n", - argv[0]); + "%s: Could not create log file.\n", argv[0]); exit(EX_SOFTWARE); } - config.syslog = FALSE; /* disable syslog */ + config.syslog = FALSE; /* disable syslog */ } else if (config.syslog) { - if (godaemon == TRUE) - openlog("tinyproxy", LOG_PID, LOG_DAEMON); - else - openlog("tinyproxy", LOG_PID, LOG_USER); - } else { + if (godaemon == TRUE) + openlog("tinyproxy", LOG_PID, LOG_DAEMON); + else + openlog("tinyproxy", LOG_PID, LOG_USER); + } else { fprintf(stderr, "%s: Either define a logfile or enable syslog logging\n", argv[0]); exit(EX_SOFTWARE); } - processed_config_file = TRUE; - send_stored_logs(); - - /* - * Set the default values if they were not set in the config file. - */ - if (config.port == 0) { - fprintf(stderr, - "%s: You MUST set a Port in the configuration file.\n", - argv[0]); - exit(EX_SOFTWARE); - } - if (!config.stathost) { - log_message(LOG_INFO, "Setting stathost to \"%s\".", - DEFAULT_STATHOST); - config.stathost = DEFAULT_STATHOST; - } - if (!config.username) { - log_message(LOG_WARNING, - "You SHOULD set a UserName in the configuration file. Using current user instead."); - } - if (config.idletimeout == 0) { - log_message(LOG_WARNING, "Invalid idle time setting. Only values greater than zero allowed; therefore setting idle timeout to %u seconds.", - MAX_IDLE_TIME); - config.idletimeout = MAX_IDLE_TIME; - } - - init_stats(); - - /* - * If ANONYMOUS is turned on, make sure that Content-Length is - * in the list of allowed headers, since it is required in a - * HTTP/1.0 request. Also add the Content-Type header since it goes - * hand in hand with Content-Length. - * - rjkaes - */ - if (is_anonymous_enabled()) { - anonymous_insert("Content-Length"); - anonymous_insert("Content-Type"); - } - - if (godaemon == TRUE) - makedaemon(); - - if (config.pidpath) { - if (pidfile_create(config.pidpath) < 0) { - fprintf(stderr, "%s: Could not create PID file.\n", - argv[0]); - exit(EX_OSERR); - } - } - - if (set_signal_handler(SIGPIPE, SIG_IGN) == SIG_ERR) { - fprintf(stderr, "%s: Could not set the \"SIGPIPE\" signal.\n", - argv[0]); - exit(EX_OSERR); - } + processed_config_file = TRUE; + send_stored_logs(); + + /* + * Set the default values if they were not set in the config file. + */ + if (config.port == 0) { + fprintf(stderr, + "%s: You MUST set a Port in the configuration file.\n", + argv[0]); + exit(EX_SOFTWARE); + } + if (!config.stathost) { + log_message(LOG_INFO, "Setting stathost to \"%s\".", + DEFAULT_STATHOST); + config.stathost = DEFAULT_STATHOST; + } + if (!config.username) { + log_message(LOG_WARNING, + "You SHOULD set a UserName in the configuration file. Using current user instead."); + } + if (config.idletimeout == 0) { + log_message(LOG_WARNING, + "Invalid idle time setting. Only values greater than zero allowed; therefore setting idle timeout to %u seconds.", + MAX_IDLE_TIME); + config.idletimeout = MAX_IDLE_TIME; + } + + init_stats(); + + /* + * If ANONYMOUS is turned on, make sure that Content-Length is + * in the list of allowed headers, since it is required in a + * HTTP/1.0 request. Also add the Content-Type header since it goes + * hand in hand with Content-Length. + * - rjkaes + */ + if (is_anonymous_enabled()) { + anonymous_insert("Content-Length"); + anonymous_insert("Content-Type"); + } + + if (godaemon == TRUE) + makedaemon(); + if (config.pidpath) { + if (pidfile_create(config.pidpath) < 0) { + fprintf(stderr, "%s: Could not create PID file.\n", + argv[0]); + exit(EX_OSERR); + } + } + + if (set_signal_handler(SIGPIPE, SIG_IGN) == SIG_ERR) { + fprintf(stderr, "%s: Could not set the \"SIGPIPE\" signal.\n", + argv[0]); + exit(EX_OSERR); + } #ifdef FILTER_ENABLE - if (config.filter) - filter_init(); -#endif /* FILTER_ENABLE */ - - /* - * Start listening on the selected port. - */ - if (child_listening_sock(config.port) < 0) { - fprintf(stderr, "%s: Could not create listening socket.\n", - argv[0]); - exit(EX_OSERR); - } - - /* - * Switch to a different user. - */ - if (geteuid() == 0) { - if (config.group && strlen(config.group) > 0) { - thisgroup = getgrnam(config.group); - if (!thisgroup) { - fprintf(stderr, - "%s: Unable to find group \"%s\".\n", - argv[0], config.group); - exit(EX_NOUSER); - } - if (setgid(thisgroup->gr_gid) < 0) { - fprintf(stderr, - "%s: Unable to change to group \"%s\".\n", - argv[0], config.group); - exit(EX_CANTCREAT); - } - log_message(LOG_INFO, "Now running as group \"%s\".", - config.group); - } - if (config.username && strlen(config.username) > 0) { - thisuser = getpwnam(config.username); - if (!thisuser) { - fprintf(stderr, - "%s: Unable to find user \"%s\".", - argv[0], config.username); - exit(EX_NOUSER); - } - if (setuid(thisuser->pw_uid) < 0) { - fprintf(stderr, - "%s: Unable to change to user \"%s\".", - argv[0], config.username); - exit(EX_CANTCREAT); - } - log_message(LOG_INFO, "Now running as user \"%s\".", - config.username); - } - } else { - log_message(LOG_WARNING, - "Not running as root, so not changing UID/GID."); - } - - if (child_pool_create() < 0) { - fprintf(stderr, "%s: Could not create the pool of children.", - argv[0]); - exit(EX_SOFTWARE); - } - - /* - * These signals are only for the parent process. - */ - log_message(LOG_INFO, "Setting the various signals."); - if (set_signal_handler(SIGCHLD, takesig) == SIG_ERR) { - fprintf(stderr, "%s: Could not set the \"SIGCHLD\" signal.\n", - argv[0]); - exit(EX_OSERR); - } - if (set_signal_handler(SIGTERM, takesig) == SIG_ERR) { - fprintf(stderr, "%s: Could not set the \"SIGTERM\" signal.\n", - argv[0]); - exit(EX_OSERR); - } - if (set_signal_handler(SIGHUP, takesig) == SIG_ERR) { - fprintf(stderr, "%s: Could not set the \"SIGHUP\" signal.\n", - argv[0]); - exit(EX_OSERR); - } - - /* - * Start the main loop. - */ - log_message(LOG_INFO, "Starting main loop. Accepting connections."); - - child_main_loop(); - - log_message(LOG_INFO, "Shutting down."); - - child_kill_children(); - child_close_sock(); - - /* - * Remove the PID file. - */ - if (unlink(config.pidpath) < 0) { - log_message(LOG_WARNING, - "Could not remove PID file \"%s\": %s.", - config.pidpath, strerror(errno)); - } + if (config.filter) + filter_init(); +#endif /* FILTER_ENABLE */ + + /* + * Start listening on the selected port. + */ + if (child_listening_sock(config.port) < 0) { + fprintf(stderr, "%s: Could not create listening socket.\n", + argv[0]); + exit(EX_OSERR); + } + + /* + * Switch to a different user. + */ + if (geteuid() == 0) { + if (config.group && strlen(config.group) > 0) { + thisgroup = getgrnam(config.group); + if (!thisgroup) { + fprintf(stderr, + "%s: Unable to find group \"%s\".\n", + argv[0], config.group); + exit(EX_NOUSER); + } + if (setgid(thisgroup->gr_gid) < 0) { + fprintf(stderr, + "%s: Unable to change to group \"%s\".\n", + argv[0], config.group); + exit(EX_CANTCREAT); + } + log_message(LOG_INFO, "Now running as group \"%s\".", + config.group); + } + if (config.username && strlen(config.username) > 0) { + thisuser = getpwnam(config.username); + if (!thisuser) { + fprintf(stderr, + "%s: Unable to find user \"%s\".", + argv[0], config.username); + exit(EX_NOUSER); + } + if (setuid(thisuser->pw_uid) < 0) { + fprintf(stderr, + "%s: Unable to change to user \"%s\".", + argv[0], config.username); + exit(EX_CANTCREAT); + } + log_message(LOG_INFO, "Now running as user \"%s\".", + config.username); + } + } else { + log_message(LOG_WARNING, + "Not running as root, so not changing UID/GID."); + } + if (child_pool_create() < 0) { + fprintf(stderr, "%s: Could not create the pool of children.", + argv[0]); + exit(EX_SOFTWARE); + } + + /* + * These signals are only for the parent process. + */ + log_message(LOG_INFO, "Setting the various signals."); + if (set_signal_handler(SIGCHLD, takesig) == SIG_ERR) { + fprintf(stderr, "%s: Could not set the \"SIGCHLD\" signal.\n", + argv[0]); + exit(EX_OSERR); + } + if (set_signal_handler(SIGTERM, takesig) == SIG_ERR) { + fprintf(stderr, "%s: Could not set the \"SIGTERM\" signal.\n", + argv[0]); + exit(EX_OSERR); + } + if (set_signal_handler(SIGHUP, takesig) == SIG_ERR) { + fprintf(stderr, "%s: Could not set the \"SIGHUP\" signal.\n", + argv[0]); + exit(EX_OSERR); + } + + /* + * Start the main loop. + */ + log_message(LOG_INFO, "Starting main loop. Accepting connections."); + + child_main_loop(); + + log_message(LOG_INFO, "Shutting down."); + + child_kill_children(); + child_close_sock(); + + /* + * Remove the PID file. + */ + if (unlink(config.pidpath) < 0) { + log_message(LOG_WARNING, + "Could not remove PID file \"%s\": %s.", + config.pidpath, strerror(errno)); + } #ifdef FILTER_ENABLE - if (config.filter) - filter_destroy(); -#endif /* FILTER_ENABLE */ + if (config.filter) + filter_destroy(); +#endif /* FILTER_ENABLE */ - if (config.syslog) - closelog(); - else - close_log_file(); + if (config.syslog) + closelog(); + else + close_log_file(); - exit(EX_OK); + exit(EX_OK); } |