main.c
来自「subversion-1.4.3-1.tar.gz 配置svn的源码」· C语言 代码 · 共 757 行 · 第 1/2 页
C
757 行
case 'd': run_mode = run_mode_daemon; mode_opt_count++; break; case SVNSERVE_OPT_FOREGROUND: foreground = TRUE; break; case 'i': run_mode = run_mode_inetd; mode_opt_count++; 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; mode_opt_count++; break; case SVNSERVE_OPT_TUNNEL_USER: params.tunnel_user = arg; break; case 'X': run_mode = run_mode_listen_once; mode_opt_count++; 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; break; case 'T': handling_mode = connection_mode_thread; break;#ifdef WIN32 case SVNSERVE_OPT_SERVICE: run_mode = run_mode_service; mode_opt_count++; break;#endif case SVNSERVE_OPT_PID_FILE: SVN_INT_ERR(svn_utf_cstring_to_utf8(&pid_filename, arg, pool)); pid_filename = svn_path_internal_style(pid_filename, pool); SVN_INT_ERR(svn_path_get_absolute(&pid_filename, pid_filename, pool)); break; } } if (os->ind != argc) usage(argv[0], pool); if (mode_opt_count != 1) { svn_error_clear(svn_cmdline_fputs (_("You must specify exactly one of -d, -i, -t or -X.\n"), stderr, pool)); usage(argv[0], pool); } if (params.tunnel_user && run_mode != run_mode_tunnel) { svn_error_clear (svn_cmdline_fprintf (stderr, pool, _("Option --tunnel-user is only valid in tunnel mode.\n"))); exit(1); } 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); status = apr_file_open_stdin(&in_file, pool); if (status) { err = svn_error_wrap_apr(status, _("Can't open stdin")); svn_handle_error2(err, stderr, FALSE, "svnserve: "); svn_error_clear(err); exit(1); } status = apr_file_open_stdout(&out_file, pool); if (status) { err = svn_error_wrap_apr(status, _("Can't open stdout")); svn_handle_error2(err, stderr, FALSE, "svnserve: "); svn_error_clear(err); exit(1); } conn = svn_ra_svn_create_conn(NULL, in_file, out_file, pool); svn_error_clear(serve(conn, ¶ms, pool)); exit(0); }#ifdef WIN32 /* If svnserve needs to run as a Win32 service, then we need to coordinate with the Service Control Manager (SCM) before continuing. This function call registers the svnserve.exe process with the SCM, waits for the "start" command from the SCM (which will come very quickly), and confirms that those steps succeeded. After this call succeeds, the service is free to run. At some point in the future, the SCM will send a message to the service, requesting that it stop. This is translated into a call to winservice_notify_stop(). The service is then responsible for cleanly terminating. We need to do this before actually starting the service logic (opening files, sockets, etc.) because the SCM wants you to connect *first*, then do your service-specific logic. If the service process takes too long to connect to the SCM, then the SCM will decide that the service is busted, and will give up on it. */ if (run_mode == run_mode_service) { err = winservice_start(); if (err) { svn_handle_error2(err, stderr, FALSE, "svnserve: "); /* This is the most common error. It means the user started svnserve from a shell, and specified the --service argument. svnserve cannot be started, as a service, in this way. The --service argument is valid only valid if svnserve is started by the SCM. */ if (err->apr_err == APR_FROM_OS_ERROR(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)) { svn_error_clear(svn_cmdline_fprintf(stderr, pool, _("svnserve: The --service flag is only valid if the" " process is started by the Service Control Manager.\n"))); } svn_error_clear(err); exit(1); } /* The service is now in the "starting" state. Before the SCM will consider the service "started", this thread must call the winservice_running() function. */ }#endif /* WIN32 */ /* Make sure we have IPV6 support first before giving apr_sockaddr_info_get APR_UNSPEC, because it may give us back an IPV6 address even if we can't create IPV6 sockets. */ #if APR_HAVE_IPV6#ifdef MAX_SECS_TO_LINGER /* ### old APR interface */ status = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, pool);#else status = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, APR_PROTO_TCP, pool);#endif if (status == 0) { apr_socket_close(sock); family = APR_UNSPEC; }#endif status = apr_sockaddr_info_get(&sa, host, family, port, 0, pool); if (status) { err = svn_error_wrap_apr(status, _("Can't get address info")); svn_handle_error2(err, stderr, FALSE, "svnserve: "); svn_error_clear(err); exit(1); }#ifdef MAX_SECS_TO_LINGER /* ### old APR interface */ status = apr_socket_create(&sock, sa->family, SOCK_STREAM, pool);#else status = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP, pool);#endif if (status) { err = svn_error_wrap_apr(status, _("Can't create server socket")); svn_handle_error2(err, stderr, FALSE, "svnserve: "); svn_error_clear(err); 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_socket_bind(sock, sa); if (status) { err = svn_error_wrap_apr(status, _("Can't bind server socket")); svn_handle_error2(err, stderr, FALSE, "svnserve: "); svn_error_clear(err); 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#ifdef SIGXFSZ /* Disable SIGXFSZ generation for the platforms that have it, otherwise * working with large files when compiled against an APR that doesn't have * large file support will crash the program, which is uncool. */ apr_signal(SIGXFSZ, SIG_IGN);#endif if (pid_filename) SVN_INT_ERR(write_pid_file(pid_filename, pool));#ifdef WIN32 status = apr_os_sock_get(&winservice_svnserve_accept_socket, sock); if (status) winservice_svnserve_accept_socket = INVALID_SOCKET; /* At this point, the service is "running". Notify the SCM. */ if (run_mode == run_mode_service) winservice_running();#endif while (1) {#ifdef WIN32 if (winservice_is_stopping()) return ERROR_SUCCESS;#endif /* 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) { err = svn_error_wrap_apr (status, _("Can't accept client connection")); svn_handle_error2(err, stderr, FALSE, "svnserve: "); svn_error_clear(err); 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_error2(err, stdout, FALSE, "svnserve: "); 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) { err = svn_error_wrap_apr(status, _("Can't create threadattr")); svn_handle_error2(err, stderr, FALSE, "svnserve: "); svn_error_clear(err); exit(1); } status = apr_threadattr_detach_set(tattr, 1); if (status) { err = svn_error_wrap_apr(status, _("Can't set detached state")); svn_handle_error2(err, stderr, FALSE, "svnserve: "); svn_error_clear(err); 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) { err = svn_error_wrap_apr(status, _("Can't create thread")); svn_handle_error2(err, stderr, FALSE, "svnserve: "); svn_error_clear(err); 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); } } /* NOTREACHED */}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?