<commit_before>/*
 * svnserve.c :  Main control function for svnserve
 *
 * ====================================================================
 *    Licensed to the Apache Software Foundation (ASF) under one
 *    or more contributor license agreements.  See the NOTICE file
 *    distributed with this work for additional information
 *    regarding copyright ownership.  The ASF licenses this file
 *    to you under the Apache License, Version 2.0 (the
 *    "License"); you may not use this file except in compliance
 *    with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing,
 *    software distributed under the License is distributed on an
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *    KIND, either express or implied.  See the License for the
 *    specific language governing permissions and limitations
 *    under the License.
 * ====================================================================
 */




#define APR_WANT_STRFUNC
#include <apr_want.h>
#include <apr_general.h>
#include <apr_getopt.h>
#include <apr_network_io.h>
#include <apr_signal.h>
#include <apr_thread_proc.h>
#include <apr_portable.h>

#include <locale.h>

#include "svn_cmdline.h"
#include "svn_types.h"
#include "svn_pools.h"
#include "svn_error.h"
#include "svn_ra_svn.h"
#include "svn_utf.h"
#include "svn_dirent_uri.h"
#include "svn_path.h"
#include "svn_opt.h"
#include "svn_repos.h"
#include "svn_string.h"
#include "svn_cache_config.h"
#include "svn_version.h"
#include "svn_io.h"

#include "svn_private_config.h"
#include "private/svn_dep_compat.h"
#include "winservice.h"

#ifdef HAVE_UNISTD_H
#include <unistd.h>   /* For getpid() */
#endif

#include "server.h"

/* The strategy for handling incoming connections.  Some of these may be
   unavailable due to platform limitations. */
enum connection_handling_mode {
  connection_mode_fork,   /* Create a process per connection */
  connection_mode_thread, /* Create a thread per connection */
  connection_mode_single  /* One connection at a time in this process */
};

/* The mode in which to run svnserve */
enum run_mode {
  run_mode_unspecified,
  run_mode_inetd,
  run_mode_daemon,
  run_mode_tunnel,
  run_mode_listen_once,
  run_mode_service
};

#if APR_HAS_FORK
#if APR_HAS_THREADS

#define CONNECTION_DEFAULT connection_mode_fork
#define CONNECTION_HAVE_THREAD_OPTION

#else /* ! APR_HAS_THREADS */

#define CONNECTION_DEFAULT connection_mode_fork

#endif /* ! APR_HAS_THREADS */
#elif APR_HAS_THREADS /* and ! APR_HAS_FORK */

#define CONNECTION_DEFAULT connection_mode_thread

#else /* ! APR_HAS_THREADS and ! APR_HAS_FORK */

#define CONNECTION_DEFAULT connection_mode_single

#endif


#ifdef WIN32
static apr_os_sock_t winservice_svnserve_accept_socket = INVALID_SOCKET;

/* The SCM calls this function (on an arbitrary thread, not the main()
   thread!) when it wants to stop the service.

   For now, our strategy is to close the listener socket, in order to
   unblock main() and cause it to exit its accept loop.  We cannot use
   apr_socket_close, because that function deletes the apr_socket_t
   structure, as well as closing the socket handle.  If we called
   apr_socket_close here, then main() will also call apr_socket_close,
   resulting in a double-free.  This way, we just close the kernel
   socket handle, which causes the accept() function call to fail,
   which causes main() to clean up the socket.  So, memory gets freed
   only once.

   This isn't pretty, but it's better than a lot of other options.
   Currently, there is no "right" way to shut down svnserve.

   We store the OS handle rather than a pointer to the apr_socket_t
   structure in order to eliminate any possibility of illegal memory
   access. */
void winservice_notify_stop(void)
{
  if (winservice_svnserve_accept_socket != INVALID_SOCKET)
    closesocket(winservice_svnserve_accept_socket);
}
#endif /* _WIN32 */


/* Option codes and descriptions for svnserve.
 *
 * The entire list must be terminated with an entry of nulls.
 *
 * APR requires that options without abbreviations
 * have codes greater than 255.
 */
#define SVNSERVE_OPT_LISTEN_PORT     256
#define SVNSERVE_OPT_LISTEN_HOST     257
#define SVNSERVE_OPT_FOREGROUND      258
#define SVNSERVE_OPT_TUNNEL_USER     259
#define SVNSERVE_OPT_VERSION         260
#define SVNSERVE_OPT_PID_FILE        261
#define SVNSERVE_OPT_SERVICE         262
#define SVNSERVE_OPT_CONFIG_FILE     263
#define SVNSERVE_OPT_LOG_FILE        264
#define SVNSERVE_OPT_CACHE_TXDELTAS  265
#define SVNSERVE_OPT_CACHE_FULLTEXTS 266
#define SVNSERVE_OPT_CACHE_REVPROPS  267
#define SVNSERVE_OPT_SINGLE_CONN     268
#define SVNSERVE_OPT_CLIENT_SPEED    269
#define SVNSERVE_OPT_VIRTUAL_HOST    270

static const apr_getopt_option_t svnserve__options[] =
  {
    {"daemon",           'd', 0, N_("daemon mode")},
    {"inetd",            'i', 0, N_("inetd mode")},
    {"tunnel",           't', 0, N_("tunnel mode")},
    {"listen-once",      'X', 0, N_("listen-once mode (useful for debugging)")},
#ifdef WIN32
    {"service",          SVNSERVE_OPT_SERVICE, 0,
     N_("Windows service mode (Service Control Manager)")},
#endif
    {"root",             'r', 1, N_("root of directory to serve")},
    {"read-only",        'R', 0,
     N_("force read only, overriding repository config file")},
    {"config-file",      SVNSERVE_OPT_CONFIG_FILE, 1,
     N_("read configuration from file ARG")},
    {"listen-port",       SVNSERVE_OPT_LISTEN_PORT, 1,
#ifdef WIN32
     N_("listen port. The default port is " APR_STRINGIFY(SVN_RA_SVN_PORT) ".\n"
        "                             "
        "[mode: daemon, service, listen-once]")},
#else
     N_("listen port. The default port is " APR_STRINGIFY(SVN_RA_SVN_PORT) ".\n"
        "                             "
        "[mode: daemon, listen-once]")},
#endif
    {"listen-host",       SVNSERVE_OPT_LISTEN_HOST, 1,
#ifdef WIN32
     N_("listen hostname or IP address\n"
        "                             "
        "By default svnserve listens on all addresses.\n"
        "                             "
        "[mode: daemon, service, listen-once]")},
#else
     N_("listen hostname or IP address\n"
        "                             "
        "By default svnserve listens on all addresses.\n"
        "                             "
        "[mode: daemon, listen-once]")},
#endif
    {"prefer-ipv6",      '6', 0,
     N_("prefer IPv6 when resolving the listen hostname\n"
        "                             "<commit_msg>Make static string literal in svnserve message gettext friendly<commit_after>/*
 * svnserve.c :  Main control function for svnserve
 *
 * ====================================================================
 *    Licensed to the Apache Software Foundation (ASF) under one
 *    or more contributor license agreements.  See the NOTICE file
 *    distributed with this work for additional information
 *    regarding copyright ownership.  The ASF licenses this file
 *    to you under the Apache License, Version 2.0 (the
 *    "License"); you may not use this file except in compliance
 *    with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing,
 *    software distributed under the License is distributed on an
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *    KIND, either express or implied.  See the License for the
 *    specific language governing permissions and limitations
 *    under the License.
 * ====================================================================
 */




#define APR_WANT_STRFUNC
#include <apr_want.h>
#include <apr_general.h>
#include <apr_getopt.h>
#include <apr_network_io.h>
#include <apr_signal.h>
#include <apr_thread_proc.h>
#include <apr_portable.h>

#include <locale.h>

#include "svn_cmdline.h"
#include "svn_types.h"
#include "svn_pools.h"
#include "svn_error.h"
#include "svn_ra_svn.h"
#include "svn_utf.h"
#include "svn_dirent_uri.h"
#include "svn_path.h"
#include "svn_opt.h"
#include "svn_repos.h"
#include "svn_string.h"
#include "svn_cache_config.h"
#include "svn_version.h"
#include "svn_io.h"

#include "svn_private_config.h"
#include "private/svn_dep_compat.h"
#include "winservice.h"

#ifdef HAVE_UNISTD_H
#include <unistd.h>   /* For getpid() */
#endif

#include "server.h"

/* The strategy for handling incoming connections.  Some of these may be
   unavailable due to platform limitations. */
enum connection_handling_mode {
  connection_mode_fork,   /* Create a process per connection */
  connection_mode_thread, /* Create a thread per connection */
  connection_mode_single  /* One connection at a time in this process */
};

/* The mode in which to run svnserve */
enum run_mode {
  run_mode_unspecified,
  run_mode_inetd,
  run_mode_daemon,
  run_mode_tunnel,
  run_mode_listen_once,
  run_mode_service
};

#if APR_HAS_FORK
#if APR_HAS_THREADS

#define CONNECTION_DEFAULT connection_mode_fork
#define CONNECTION_HAVE_THREAD_OPTION

#else /* ! APR_HAS_THREADS */

#define CONNECTION_DEFAULT connection_mode_fork

#endif /* ! APR_HAS_THREADS */
#elif APR_HAS_THREADS /* and ! APR_HAS_FORK */

#define CONNECTION_DEFAULT connection_mode_thread

#else /* ! APR_HAS_THREADS and ! APR_HAS_FORK */

#define CONNECTION_DEFAULT connection_mode_single

#endif


#ifdef WIN32
static apr_os_sock_t winservice_svnserve_accept_socket = INVALID_SOCKET;

/* The SCM calls this function (on an arbitrary thread, not the main()
   thread!) when it wants to stop the service.

   For now, our strategy is to close the listener socket, in order to
   unblock main() and cause it to exit its accept loop.  We cannot use
   apr_socket_close, because that function deletes the apr_socket_t
   structure, as well as closing the socket handle.  If we called
   apr_socket_close here, then main() will also call apr_socket_close,
   resulting in a double-free.  This way, we just close the kernel
   socket handle, which causes the accept() function call to fail,
   which causes main() to clean up the socket.  So, memory gets freed
   only once.

   This isn't pretty, but it's better than a lot of other options.
   Currently, there is no "right" way to shut down svnserve.

   We store the OS handle rather than a pointer to the apr_socket_t
   structure in order to eliminate any possibility of illegal memory
   access. */
void winservice_notify_stop(void)
{
  if (winservice_svnserve_accept_socket != INVALID_SOCKET)
    closesocket(winservice_svnserve_accept_socket);
}
#endif /* _WIN32 */


/* Option codes and descriptions for svnserve.
 *
 * The entire list must be terminated with an entry of nulls.
 *
 * APR requires that options without abbreviations
 * have codes greater than 255.
 */
#define SVNSERVE_OPT_LISTEN_PORT     256
#define SVNSERVE_OPT_LISTEN_HOST     257
#define SVNSERVE_OPT_FOREGROUND      258
#define SVNSERVE_OPT_TUNNEL_USER     259
#define SVNSERVE_OPT_VERSION         260
#define SVNSERVE_OPT_PID_FILE        261
#define SVNSERVE_OPT_SERVICE         262
#define SVNSERVE_OPT_CONFIG_FILE     263
#define SVNSERVE_OPT_LOG_FILE        264
#define SVNSERVE_OPT_CACHE_TXDELTAS  265
#define SVNSERVE_OPT_CACHE_FULLTEXTS 266
#define SVNSERVE_OPT_CACHE_REVPROPS  267
#define SVNSERVE_OPT_SINGLE_CONN     268
#define SVNSERVE_OPT_CLIENT_SPEED    269
#define SVNSERVE_OPT_VIRTUAL_HOST    270

static const apr_getopt_option_t svnserve__options[] =
  {
    {"daemon",           'd', 0, N_("daemon mode")},
    {"inetd",            'i', 0, N_("inetd mode")},
    {"tunnel",           't', 0, N_("tunnel mode")},
    {"listen-once",      'X', 0, N_("listen-once mode (useful for debugging)")},
#ifdef WIN32
    {"service",          SVNSERVE_OPT_SERVICE, 0,
     N_("Windows service mode (Service Control Manager)")},
#endif
    {"root",             'r', 1, N_("root of directory to serve")},
    {"read-only",        'R', 0,
     N_("force read only, overriding repository config file")},
    {"config-file",      SVNSERVE_OPT_CONFIG_FILE, 1,
     N_("read configuration from file ARG")},
    {"listen-port",       SVNSERVE_OPT_LISTEN_PORT, 1,
#ifdef WIN32
     N_("listen port. The default port is 3690.\n"
        "                             "
        "[mode: daemon, service, listen-once]")},
#else
     N_("listen port. The default port is 3690.\n"
        "                             "
        "[mode: daemon, listen-once]")},
#endif
    {"listen-host",       SVNSERVE_OPT_LISTEN_HOST, 1,
#ifdef WIN32
     N_("listen hostname or IP address\n"
        "                             "
        "By default svnserve listens on all addresses.\n"
        "                             "
        "[mode: daemon, service, listen-once]")},
#else
     N_("listen hostname or IP address\n"
        "                             "
        "By default svnserve listens on all addresses.\n"
        "                             "
        "[mode: daemon, listen-once]")},
#endif
    {"prefer-ipv6",      '6', 0,
     N_("prefer IPv6 when resolving the listen hostname\n"
        "                             "
{'fraction_non_alphanumeric': 0.1078505521101195, 'fraction_numerical': 0.01210104371502042, 'mean_word_length': 3.220555378231727, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '793880', 'n_tokens_mistral': 4347, 'n_tokens_neox': 4173, 'n_words': 1302}