📄 main.c
字号:
params.root = "/";
params.tunnel = FALSE;
params.tunnel_user = NULL;
params.read_only = FALSE;
while (1)
{
status = apr_getopt_long(os, svnserve__options, &opt, &arg);
if (APR_STATUS_IS_EOF(status))
break;
if (status != APR_SUCCESS)
usage(argv[0]);
switch (opt)
{
case 'h':
help(pool);
break;
case SVNSERVE_OPT_VERSION:
SVN_INT_ERR(version(os, pool));
exit(0);
break;
case 'd':
run_mode = run_mode_daemon;
break;
case SVNSERVE_OPT_FOREGROUND:
foreground = TRUE;
break;
case 'i':
run_mode = run_mode_inetd;
break;
case SVNSERVE_OPT_LISTEN_PORT:
port = atoi(arg);
break;
case SVNSERVE_OPT_LISTEN_HOST:
host = arg;
break;
case 't':
run_mode = run_mode_tunnel;
break;
case SVNSERVE_OPT_TUNNEL_USER:
params.tunnel_user = arg;
break;
case 'X':
run_mode = run_mode_listen_once;
break;
case 'r':
SVN_INT_ERR(svn_utf_cstring_to_utf8(¶ms.root, arg, pool));
params.root = svn_path_internal_style(params.root, pool);
SVN_INT_ERR(svn_path_get_absolute(¶ms.root, params.root, pool));
break;
case 'R':
params.read_only = TRUE;
fprintf(stderr, "Warning: -R is deprecated.\n");
fprintf(stderr, "Anonymous access is now read-only by default.\n");
fprintf(stderr, "To change, use conf/svnserve.conf in repos:\n");
fprintf(stderr, " [general]\n");
fprintf(stderr, " anon-access = read|write|none (default read)\n");
fprintf(stderr, " auth-access = read|write|none (default write)\n");
fprintf(stderr, "Forcing all access to read-only for now\n");
break;
case 'T':
handling_mode = connection_mode_thread;
break;
}
}
if (os->ind != argc)
usage(argv[0]);
if (params.tunnel_user && run_mode != run_mode_tunnel)
{
fprintf(stderr, "Option --tunnel-user is only valid in tunnel mode.\n");
exit(1);
}
if (run_mode == run_mode_none)
{
fprintf(stderr, "You must specify one of -d, -i, -t or -X.\n");
usage(argv[0]);
}
if (run_mode == run_mode_inetd || run_mode == run_mode_tunnel)
{
params.tunnel = (run_mode == run_mode_tunnel);
apr_pool_cleanup_register(pool, pool, apr_pool_cleanup_null,
redirect_stdout);
apr_file_open_stdin(&in_file, pool);
apr_file_open_stdout(&out_file, pool);
conn = svn_ra_svn_create_conn(NULL, in_file, out_file, pool);
svn_error_clear(serve(conn, ¶ms, pool));
exit(0);
}
#ifdef MAX_SECS_TO_LINGER
/* ### old APR interface */
status = apr_socket_create(&sock, APR_INET, SOCK_STREAM, pool);
#else
status = apr_socket_create(&sock, APR_INET, SOCK_STREAM, APR_PROTO_TCP,
pool);
#endif
if (status)
{
fprintf(stderr, "Can't create server socket: %s\n",
apr_strerror(status, errbuf, sizeof(errbuf)));
exit(1);
}
/* Prevents "socket in use" errors when server is killed and quickly
* restarted. */
apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
status = apr_sockaddr_info_get(&sa, host, APR_INET, port, 0, pool);
if (status)
{
fprintf(stderr, "Can't get address info: %s\n",
apr_strerror(status, errbuf, sizeof(errbuf)));
exit(1);
}
status = apr_socket_bind(sock, sa);
if (status)
{
fprintf(stderr, "Can't bind server socket: %s\n",
apr_strerror(status, errbuf, sizeof(errbuf)));
exit(1);
}
apr_socket_listen(sock, 7);
#if APR_HAS_FORK
if (run_mode != run_mode_listen_once && !foreground)
apr_proc_detach(APR_PROC_DETACH_DAEMONIZE);
apr_signal(SIGCHLD, sigchld_handler);
#endif
#ifdef SIGPIPE
/* Disable SIGPIPE generation for the platforms that have it. */
apr_signal(SIGPIPE, SIG_IGN);
#endif
while (1)
{
/* Non-standard pool handling. The main thread never blocks to join
the connection threads so it cannot clean up after each one. So
separate pools, that can be cleared at thread exit, are used */
connection_pool = svn_pool_create(NULL);
status = apr_socket_accept(&usock, sock, connection_pool);
if (handling_mode == connection_mode_fork)
{
/* Collect any zombie child processes. */
while (apr_proc_wait_all_procs(&proc, NULL, NULL, APR_NOWAIT,
connection_pool) == APR_CHILD_DONE)
;
}
if (APR_STATUS_IS_EINTR(status))
{
svn_pool_destroy(connection_pool);
continue;
}
if (status)
{
fprintf(stderr, "Can't accept client connection: %s\n",
apr_strerror(status, errbuf, sizeof(errbuf)));
exit(1);
}
conn = svn_ra_svn_create_conn(usock, NULL, NULL, connection_pool);
if (run_mode == run_mode_listen_once)
{
err = serve(conn, ¶ms, connection_pool);
if (err && err->apr_err != SVN_ERR_RA_SVN_CONNECTION_CLOSED)
svn_handle_error(err, stdout, FALSE);
svn_error_clear(err);
apr_socket_close(usock);
apr_socket_close(sock);
exit(0);
}
switch (handling_mode)
{
case connection_mode_fork:
#if APR_HAS_FORK
status = apr_proc_fork(&proc, connection_pool);
if (status == APR_INCHILD)
{
apr_socket_close(sock);
svn_error_clear(serve(conn, ¶ms, connection_pool));
apr_socket_close(usock);
exit(0);
}
else if (status == APR_INPARENT)
{
apr_socket_close(usock);
}
else
{
/* Log an error, when we support logging. */
apr_socket_close(usock);
}
svn_pool_destroy(connection_pool);
#endif
break;
case connection_mode_thread:
/* Create a detached thread for each connection. That's not a
particularly sophisticated strategy for a threaded server, it's
little different from forking one process per connection. */
#if APR_HAS_THREADS
status = apr_threadattr_create(&tattr, connection_pool);
if (status)
{
fprintf(stderr, "Can't create threadattr: %s\n",
apr_strerror(status, errbuf, sizeof(errbuf)));
exit(1);
}
status = apr_threadattr_detach_set(tattr, 1);
if (status)
{
fprintf(stderr, "Can't set detached state: %s\n",
apr_strerror(status, errbuf, sizeof(errbuf)));
exit(1);
}
thread_data = apr_palloc(connection_pool, sizeof(*thread_data));
thread_data->conn = conn;
thread_data->params = ¶ms;
thread_data->pool = connection_pool;
status = apr_thread_create(&tid, tattr, serve_thread, thread_data,
connection_pool);
if (status)
{
fprintf(stderr, "Can't create thread: %s\n",
apr_strerror(status, errbuf, sizeof(errbuf)));
exit(1);
}
#endif
break;
case connection_mode_single:
/* Serve one connection at a time. */
svn_error_clear(serve(conn, ¶ms, connection_pool));
svn_pool_destroy(connection_pool);
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -