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(&params.root, arg, pool));          params.root = svn_path_internal_style(params.root, pool);          SVN_INT_ERR(svn_path_get_absolute(&params.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, &params, 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, &params, 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, &params, 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 = &params;          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, &params, connection_pool));          svn_pool_destroy(connection_pool);        }    }  /* NOTREACHED */}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?