⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unixd.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 2 页
字号:
                              const char * const *env,                              apr_procattr_t *attr, ap_unix_identity_t *ugid,                              apr_pool_t *p){    int i = 0;    const char **newargs;    char *newprogname;    char *execuser, *execgroup;    const char *argv0;    if (!unixd_config.suexec_enabled) {        return apr_proc_create(newproc, progname, args, env, attr, p);    }    argv0 = ap_strrchr_c(progname, '/');    /* Allow suexec's "/" check to succeed */    if (argv0 != NULL) {        argv0++;    }    else {        argv0 = progname;    }    if (ugid->userdir) {        execuser = apr_psprintf(p, "~%ld", (long) ugid->uid);    }    else {        execuser = apr_psprintf(p, "%ld", (long) ugid->uid);    }    execgroup = apr_psprintf(p, "%ld", (long) ugid->gid);    if (!execuser || !execgroup) {        return APR_ENOMEM;    }    i = 0;    if (args) {        while (args[i]) {            i++;	    }    }    /* allocate space for 4 new args, the input args, and a null terminator */    newargs = apr_palloc(p, sizeof(char *) * (i + 4));    newprogname = SUEXEC_BIN;    newargs[0] = SUEXEC_BIN;    newargs[1] = execuser;    newargs[2] = execgroup;    newargs[3] = apr_pstrdup(p, argv0);    /*    ** using a shell to execute suexec makes no sense thus    ** we force everything to be APR_PROGRAM, and never    ** APR_SHELLCMD    */    if(apr_procattr_cmdtype_set(attr, APR_PROGRAM) != APR_SUCCESS) {        return APR_EGENERAL;    }    i = 1;    do {        newargs[i + 3] = args[i];    } while (args[i++]);    return apr_proc_create(newproc, newprogname, newargs, env, attr, p);}AP_DECLARE(apr_status_t) ap_os_create_privileged_process(    const request_rec *r,    apr_proc_t *newproc, const char *progname,    const char * const *args,    const char * const *env,    apr_procattr_t *attr, apr_pool_t *p){    ap_unix_identity_t *ugid = ap_run_get_suexec_identity(r);    if (ugid == NULL) {        return apr_proc_create(newproc, progname, args, env, attr, p);    }    return ap_unix_create_privileged_process(newproc, progname, args, env,                                              attr, ugid, p);}/* XXX move to APR and externalize (but implement differently :) ) */static apr_lockmech_e proc_mutex_mech(apr_proc_mutex_t *pmutex){    const char *mechname = apr_proc_mutex_name(pmutex);    if (!strcmp(mechname, "sysvsem")) {        return APR_LOCK_SYSVSEM;    }    else if (!strcmp(mechname, "flock")) {        return APR_LOCK_FLOCK;    }    return APR_LOCK_DEFAULT;}AP_DECLARE(apr_status_t) unixd_set_proc_mutex_perms(apr_proc_mutex_t *pmutex){    if (!geteuid()) {        apr_lockmech_e mech = proc_mutex_mech(pmutex);        switch(mech) {#if APR_HAS_SYSVSEM_SERIALIZE        case APR_LOCK_SYSVSEM:        {            apr_os_proc_mutex_t ospmutex;#if !APR_HAVE_UNION_SEMUN            union semun {                long val;                struct semid_ds *buf;                unsigned short *array;            };#endif            union semun ick;            struct semid_ds buf;                    apr_os_proc_mutex_get(&ospmutex, pmutex);            buf.sem_perm.uid = unixd_config.user_id;            buf.sem_perm.gid = unixd_config.group_id;            buf.sem_perm.mode = 0600;            ick.buf = &buf;            if (semctl(ospmutex.crossproc, 0, IPC_SET, ick) < 0) {                return errno;            }        }        break;#endif#if APR_HAS_FLOCK_SERIALIZE        case APR_LOCK_FLOCK:        {            const char *lockfile = apr_proc_mutex_lockfile(pmutex);            if (lockfile) {                if (chown(lockfile, unixd_config.user_id,                          -1 /* no gid change */) < 0) {                    return errno;                }            }        }        break;#endif        default:            /* do nothing */            break;        }    }    return APR_SUCCESS;}AP_DECLARE(apr_status_t) unixd_set_global_mutex_perms(apr_global_mutex_t *gmutex){#if !APR_PROC_MUTEX_IS_GLOBAL    apr_os_global_mutex_t osgmutex;    apr_os_global_mutex_get(&osgmutex, gmutex);    return unixd_set_proc_mutex_perms(osgmutex.proc_mutex);#else  /* APR_PROC_MUTEX_IS_GLOBAL */    /* In this case, apr_proc_mutex_t and apr_global_mutex_t are the same. */    return unixd_set_proc_mutex_perms(gmutex);#endif /* APR_PROC_MUTEX_IS_GLOBAL */}AP_DECLARE(apr_status_t) unixd_accept(void **accepted, ap_listen_rec *lr,                                        apr_pool_t *ptrans){    apr_socket_t *csd;    apr_status_t status;    *accepted = NULL;    status = apr_accept(&csd, lr->sd, ptrans);    if (status == APR_SUCCESS) {         *accepted = csd;        return APR_SUCCESS;    }    if (APR_STATUS_IS_EINTR(status)) {        return status;    }    /* Our old behaviour here was to continue after accept()     * errors.  But this leads us into lots of troubles     * because most of the errors are quite fatal.  For     * example, EMFILE can be caused by slow descriptor     * leaks (say in a 3rd party module, or libc).  It's     * foolish for us to continue after an EMFILE.  We also     * seem to tickle kernel bugs on some platforms which     * lead to never-ending loops here.  So it seems best     * to just exit in most cases.     */    switch (status) {#if defined(HPUX11) && defined(ENOBUFS)        /* On HPUX 11.x, the 'ENOBUFS, No buffer space available'         * error occurs because the accept() cannot complete.         * You will not see ENOBUFS with 10.20 because the kernel         * hides any occurrence from being returned to user space.         * ENOBUFS with 11.x's TCP/IP stack is possible, and could         * occur intermittently. As a work-around, we are going to         * ignore ENOBUFS.         */        case ENOBUFS:#endif#ifdef EPROTO        /* EPROTO on certain older kernels really means         * ECONNABORTED, so we need to ignore it for them.         * See discussion in new-httpd archives nh.9701         * search for EPROTO.         *         * Also see nh.9603, search for EPROTO:         * There is potentially a bug in Solaris 2.x x<6,         * and other boxes that implement tcp sockets in         * userland (i.e. on top of STREAMS).  On these         * systems, EPROTO can actually result in a fatal         * loop.  See PR#981 for example.  It's hard to         * handle both uses of EPROTO.         */        case EPROTO:#endif#ifdef ECONNABORTED        case ECONNABORTED:#endif        /* Linux generates the rest of these, other tcp         * stacks (i.e. bsd) tend to hide them behind         * getsockopt() interfaces.  They occur when         * the net goes sour or the client disconnects         * after the three-way handshake has been done         * in the kernel but before userland has picked         * up the socket.         */#ifdef ECONNRESET        case ECONNRESET:#endif#ifdef ETIMEDOUT        case ETIMEDOUT:#endif#ifdef EHOSTUNREACH        case EHOSTUNREACH:#endif#ifdef ENETUNREACH        case ENETUNREACH:#endif        /* EAGAIN/EWOULDBLOCK can be returned on BSD-derived         * TCP stacks when the connection is aborted before         * we call connect, but only because our listener         * sockets are non-blocking (AP_NONBLOCK_WHEN_MULTI_LISTEN)         */#ifdef EAGAIN        case EAGAIN:#endif#ifdef EWOULDBLOCK#if !defined(EAGAIN) || EAGAIN != EWOULDBLOCK        case EWOULDBLOCK:#endif#endif            break;#ifdef ENETDOWN        case ENETDOWN:            /*             * When the network layer has been shut down, there             * is not much use in simply exiting: the parent             * would simply re-create us (and we'd fail again).             * Use the CHILDFATAL code to tear the server down.             * @@@ Martin's idea for possible improvement:             * A different approach would be to define             * a new APEXIT_NETDOWN exit code, the reception             * of which would make the parent shutdown all             * children, then idle-loop until it detected that             * the network is up again, and restart the children.             * Ben Hyde noted that temporary ENETDOWN situations             * occur in mobile IP.             */            ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf,                         "apr_accept: giving up.");            return APR_EGENERAL;#endif /*ENETDOWN*/#ifdef TPF        case EINACT:            ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf,                         "offload device inactive");            return APR_EGENERAL;            break;        default:            ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,                         "select/accept error (%d)", status);            return APR_EGENERAL;#else        default:            ap_log_error(APLOG_MARK, APLOG_ERR, status, ap_server_conf,                         "apr_accept: (client socket)");            return APR_EGENERAL;#endif    }    return status;}

⌨️ 快捷键说明

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