`
glintstar
  • 浏览: 12551 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Ace

    博客分类:
  • ACE
阅读更多
#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <sys/times.h>
#include <stdlib.h>
#include <sys/wait.h>

#include "ace/SOCK_Stream.h"
#include "ace/INET_Addr.h"
#include "ace/OS.h"
#include "ace/SOCK_Dgram.h"
#include "ace/INET_Addr.h"
#include "ace/Reactor.h"
#include "ace/Synch.h"
#include "ace/OS.h"
#include "ace/INET_Addr.h"
#include "ace/Acceptor.h"
#include "ace/Connector.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/SOCK_Connector.h"
#include "ace/Reactor.h"
#include "ace/SOCK_Stream.h"
#include "ace/SOCK_Dgram.h"
#include "ace/Log_Msg.h"
#include "ace/Log_Priority.h"
#include "ace/Get_Opt.h"
#include "time.h"
#include "pexec_share.h"
#include "wd.h"


// global variables
//struct buff_stdout outbuff;
//struct buff_stderr errbuff;
//int exitcode;
extern int errno;

enum status_type  execprocess(char* uname,
                              char* cmdline,
                              int nmili_sec,
                              int& exitcode,
      struct buff_stdout& outbuff,
                              struct buff_stderr& errbuff);


class PEXEC_Handler:
            public ACE_Svc_Handler<ACE_SOCK_STREAM,ACE_MT_SYNCH>
{
public:
    PEXEC_Handler(){
}
    int init();
    int open(void*);
    int handle_input(ACE_HANDLE);
int handle_timeout(const ACE_Time_Value&, const void*);
    int handle_close(ACE_HANDLE,ACE_Reactor_Mask);
    int svc();
private:
    param_pack pex_pps;
    ACE_Thread_Mutex mutex_;
};

typedef   ACE_Acceptor<PEXEC_Handler, ACE_SOCK_ACCEPTOR>    PEXEC_Acceptor;

int
PEXEC_Handler::open(void *)
{
    //ACE_DEBUG((LM_DEBUG,"the gsd_handler is going to be opened\n"));
    ACE_Reactor::instance()->register_handler(this,ACE_Event_Handler::READ_MASK);
    return 0;
}

int
PEXEC_Handler::handle_input(ACE_HANDLE)
{
   // int rlen = peer().recv(tmp_recv,128,0);
    struct param_pack pps, net_pps;
    //enum status_type exec_status;
    //int nint;

    int rlen = peer().recv((char *)&net_pps, sizeof(net_pps), 0);
    if (rlen <= -1) // can not recv messge from client
    {
        cout << "[" << __FILE__ << ":" << __LINE__ << "]" << "\t";
        /*new  add 0525*/
        peer().close();
        /*end add*/
        ACE_ERROR_RETURN((LM_ERROR,"(%P|%t, %p)","recv message failed"),-1);
        return -1;
    }
    if (rlen == 0){
       peer().close();
       return -1;
    }

    //convert net_pps to pps
    strncpy(pps.user, net_pps.user, sizeof(pps.user));
    strncpy(pps.cmdline, net_pps.cmdline, sizeof(pps.cmdline));
    pps.fexitcode = ntohl(net_pps.fexitcode);
    pps.milisec = ntohl(net_pps.milisec);
    //cout<<"user name is "<<pps.user<<endl
    //  <<"cmdline is "<<pps.cmdline<<endl
    //<<"exitcode only is "<<pps.exitcode_only<<endl
    //<<"timeout is "<<pps.timeout<<endl;

    mutex_.acquire();
    pex_pps = net_pps;

    activate(THR_NEW_LWP,
            1, //2 new threads
            1, //force active false, if already created don~Rt try again.
            ACE_DEFAULT_THREAD_PRIORITY,//Use default thread priority
            -1,
            this,//Which ACE_Task object to create? In this case this one.
            0,// don~Rt care about thread handles used
            0,// don~Rt care about where stacks are created
            0);//don~Rt care about stack sizes
            //thread_names); // keep identifiers in thread_names

    return 0;
}

int
PEXEC_Handler::handle_close(ACE_HANDLE,ACE_Reactor_Mask)
{
    return 0;
}

int
PEXEC_Handler::handle_timeout(const ACE_Time_Value&, const void*) {

    send_wd_heartbeat(PEXEC_SRC_TYPE);
return 0;
}

int
PEXEC_Handler::svc() {

    struct buff_stdout outbuff;
    struct buff_stderr errbuff;
    int exitcode;
    status_type exec_status;
    int nint;
    param_pack pps;

    pps = pex_pps;
    mutex_.release();

    //exec cmdline
    exec_status = execprocess(pps.user,
                              pps.cmdline,
                              pps.milisec,
                              exitcode,
                              outbuff,
                              errbuff);
    nint = htonl(exec_status);
    if (peer().send_n((char *)&nint, sizeof(nint), 0) == -1){
        ACE_DEBUG((LM_DEBUG, ACE_TEXT("send data error : %s"),
                     ACE_OS::strerror(ACE_OS::last_error())));
        return -1;
    }
    //cout<<"errbuff.len = "<<errbuff.len<<endl;
    //cout<<errbuff.buffer<<endl;
    if (exec_status == EXEC_SUCCESS) {
        //send exit code back
        nint = htonl(exitcode);
        if (peer().send_n((char *)&nint, sizeof(nint)) == -1) {
            ACE_DEBUG((LM_DEBUG, ACE_TEXT("send data error : %s"),
                         ACE_OS::strerror(ACE_OS::last_error())));
            //ACE_OS::printf("send data failed\n");
            return -1;
        }
        if (pps.fexitcode) {
            //send stdout len back
            nint = htonl(outbuff.len);
            if (peer().send_n((char *)&nint, sizeof(nint), 0) == -1) {
                //ACE_OS::printf("send data failed\n");
                ACE_DEBUG((LM_DEBUG, ACE_TEXT("send data error : %s"),
                             ACE_OS::strerror(ACE_OS::last_error())));
                return -1;
            }
            if (outbuff.len > 0) {
                if (peer().send_n(outbuff.buffer, outbuff.len, 0) == -1) {
                    //ACE_OS::printf("send data failed\n");
                    ACE_DEBUG((LM_DEBUG, ACE_TEXT("send data error : %s"),
                                 ACE_OS::strerror(ACE_OS::last_error())));
                    return -1;
                }
            }

            //send stderr len back
            nint = htonl(errbuff.len);
            if (peer().send_n((char *)&nint, sizeof(nint), 0) == -1) {
                //ACE_OS::printf("send data failed\n");
                ACE_DEBUG((LM_DEBUG, ACE_TEXT("send data error : %s"),
                             ACE_OS::strerror(ACE_OS::last_error())));
                return -1;
            }
            if (errbuff.len > 0) {
                if (peer().send_n(errbuff.buffer, errbuff.len, 0) == -1) {
                    //ACE_OS::printf("send data failed\n");
                    ACE_DEBUG((LM_DEBUG, ACE_TEXT("send data error : %s"),
                                 ACE_OS::strerror(ACE_OS::last_error())));
                    return -1;
                }
            }
        }
    }
    // peer().close();
    return 0;
}

int main(int argc, char** argv)
{
    ACE_INET_Addr    tcp_addr(PEXEC_PORT);
    ACE_INET_Addr    remote_addr;
    PEXEC_Acceptor     *acceptor;

    ACE::daemonize();
    //open log
    ofstream *output_file = new ofstream("/home/dware/pexecd.log", ios::out);
    if (output_file && output_file->rdstate() == ios::goodbit)
ACE_LOG_MSG->msg_ostream(output_file, 1);
ACE_LOG_MSG->open(argv[0], ACE_Log_Msg::OSTREAM,0);
ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%T (%t): Starting service.\n")));

    acceptor = new PEXEC_Acceptor;

    if(acceptor->open(tcp_addr, ACE_Reactor::instance()) == -1)
    {
        char error_message[64];
        printf("[%s|%d]open failed: %s", __FILE__, __LINE__,  strerror(errno));
    }

PEXEC_Handler My_Pexec_Handler;
    ACE_Time_Value timeout(HB_TIMEOUT);
ACE_Reactor::instance()->schedule_timer(&My_Pexec_Handler,0,timeout,timeout);

    while(1)       
        ACE_Reactor::instance()->handle_events();

    return 0;
}

status_type execprocess(char* uname,
                        char* cmdline,
                        int nmili_sec,
                        int& exitcode,
                        struct buff_stdout& outbuff,
                struct buff_stderr& errbuff) {

    int chuser;
    struct passwd *pw;
    int pp_out[2], pp_err[2];
    pid_t pid;
    uid_t uid;
    gid_t gid;
    char *shellpath, *shellname;
    fd_set readfd, allfd;
    int nfds, rt_sel;
    struct timeval tm;
    int nrd_out, nrd_err;
    size_t nleft_out, nleft_err;
    char *ppos_out, *ppos_err;
    char buff_rub[BUFF_SIZ];
    int status;
    int i;
//enum status_type exec_status;

    chuser = strcmp(uname, "root"); /* if we are required to change user id */
    //printf("chuser is %d\n", chuser);

    if ((pw = getpwnam(uname)) == NULL) { /* get passwd file entry */
        ACE_DEBUG((LM_DEBUG, ACE_TEXT("getpwnam error : %s"), strerror(errno)));
        return ERR_EXEC_COMMAND;
    }
    uid = pw->pw_uid;
    gid = pw->pw_gid;
    //printf("%s : uid is %d, gid is %d\n", uname, uid, gid);

    /* create pipes for stdout and stderr of child process */
    if (pipe(pp_out) != 0) {
        ACE_DEBUG((LM_DEBUG, ACE_TEXT("create stdout pipe error : %s"), strerror(errno)));
        return ERR_EXEC_COMMAND;
    }
    if (pipe(pp_err) != 0) {
        ACE_DEBUG((LM_DEBUG, ACE_TEXT("create stderr pipe error : %s"), strerror(errno)));
        return ERR_EXEC_COMMAND;
    }

    /* create child process */
    pid = fork();
    if (pid < 0) {
        ACE_DEBUG((LM_DEBUG, ACE_TEXT("fork error : %s"), strerror(errno)));
        return ERR_EXEC_COMMAND;
    }
    if (pid == 0) { /* child process */

        close(pp_out[0]); /* close read end of stdout pipe */
        close(pp_err[0]); /* close read end of stderr pipe */
       
        if (dup2(pp_out[1], 1) == -1) { /* make stdout a copy of write end of pipe */
            ACE_DEBUG((LM_DEBUG, ACE_TEXT("dup error : %s"), strerror(errno)));
            return ERR_EXEC_COMMAND;
        }
        close(pp_out[1]);

        if (dup2(pp_err[1], 2) == -1) { /* make stderr a copy of write end of pipe */
            ACE_DEBUG((LM_DEBUG, ACE_TEXT("dup error : %s"), strerror(errno)));
            return ERR_EXEC_COMMAND;
        }
        close(pp_err[1]);

        if (chuser != 0) {
            //printf("now changing uid and gid\n");
            uid = pw->pw_uid;
            gid = pw->pw_gid;
            errno = 0;
            if (setgid(gid) != 0) {
                ACE_DEBUG((LM_DEBUG, ACE_TEXT("setgid error : %s"), strerror(errno)));
                return ERR_EXEC_COMMAND;
            }
            if (setuid(uid) != 0) {
                ACE_DEBUG((LM_DEBUG, ACE_TEXT("setuid error : %s"), strerror(errno)));
                return ERR_EXEC_COMMAND;
            }
        }

        for (i = 3; i < 65536; i++)
            ACE_OS::close(i);
        //printf("now uid is %d, gid is %d\n", getuid(), getgid());
        shellpath = pw->pw_shell;
        shellname = strrchr(shellpath, '/');
        execl(shellpath, shellname, "-c", cmdline, NULL); /* execute new process */
        perror("");
        exit(EXIT_FAILURE);
    }
    /* in parent process */
    close(pp_out[1]); /* close write end of stdout pipe */
    close(pp_err[1]); /* close write end of stderr pipe */

    /* get num of fds to detect */
    nfds = (pp_out[0] > pp_err[0]) ? pp_out[0] : pp_err[0];
    nfds++;

    /* initialization */
    tm.tv_usec = (nmili_sec % 1000) * 1000;
    tm.tv_sec = nmili_sec / 1000;
    nleft_out = STDOUT_BUFF_SIZ;
    nleft_err = STDERR_BUFF_SIZ;
    outbuff.len = errbuff.len = 0;
    ppos_out = outbuff.buffer;
    ppos_err = errbuff.buffer;
    nrd_out = nrd_err = 0;

    FD_ZERO(&allfd);
    FD_SET(pp_out[0], &allfd);
    FD_SET(pp_err[0], &allfd);

    while (1) {
        readfd = allfd;
        if (nmili_sec > 0)
            rt_sel = select(nfds, &readfd, NULL, NULL, &tm);
        else
            rt_sel = select(nfds, &readfd, NULL, NULL, NULL);
        if (rt_sel > 0) {
            if (FD_ISSET(pp_out[0], &readfd) != 0) {
                if (nleft_out > 0) {
                    nrd_out = read(pp_out[0], ppos_out, nleft_out);
                    if (nrd_out > 0) {
                        ppos_out += nrd_out;
                        //outbuff.len += nrd_out;
                        nleft_out -= nrd_out;
                    }
                }
                else
                    nrd_out = read(pp_out[0], buff_rub, sizeof(buff_rub));
            }
            if (FD_ISSET(pp_err[0], &readfd) != 0) {
                if (nleft_err > 0) {
                    nrd_err = read(pp_err[0], ppos_err, nleft_err);
                    if (nrd_err > 0) {
                        ppos_err += nrd_err;
                        //errbuff.len += nrd_err;
                        nleft_err -= nrd_err;
                    }
                }
                else
                    nrd_err = read(pp_err[0], buff_rub, sizeof(buff_rub));
            }
            if (nrd_out == 0 && nrd_err == 0) {
                outbuff.len = STDOUT_BUFF_SIZ - nleft_out;
                errbuff.len = STDERR_BUFF_SIZ - nleft_err;
                *ppos_out = *ppos_err = '\0';
                break;
            }
        }
        else
            if (rt_sel == 0) {//time out
                return ERR_EXEC_TIMEOUT;
           }
            else
                if (rt_sel < 0) {
                  if (errno == EINTR) {
                      tm.tv_sec =  nmili_sec / 1000; /* reset the timeout value */
                      tm.tv_usec = 0;
                      //printf("error\n");
                      continue;
                  }
                  else
                    break;
                }
    }
    wait(&status);
    if (WIFEXITED(status)) {
        exitcode = WEXITSTATUS(status);
return EXEC_SUCCESS;
    }
    else
        return ERR_INVALID_EXITCODE;

    //turn exec_status;

}
分享到:
评论

相关推荐

    Ace Admin 前端框架

    Ace Admin 是一个强大的前端框架,专为开发企业级Web应用后台管理系统而设计。这个框架以其高效、可定制性高和用户界面友好而受到广大开发者欢迎。Ace Admin 的核心是基于Bootstrap,一个流行的前端开发框架,这使得...

    ACE完整牛逼定时器

    **ACE完整牛逼定时器详解** ACE(Adaptive Communication Environment)是一个开源的、跨平台的C++库,专为分布式实时系统设计,提供了一系列高级网络编程接口和工具。在这个“ACE完整牛逼定时器”中,我们将深入...

    ace.js实现的编辑器

    ace.js编辑器是一个功能强大的开源代码编辑器,它以JavaScript为基础,并通过浏览器提供丰富的编辑功能。以下是关于ace.js编辑器的详细描述: 首先,ace.js编辑器支持多种编程语言,包括但不限于JavaScript、HTML、...

    bootstrap-ace_tab

    Bootstrap Ace Tab是一个基于Bootstrap和ACE框架的前端页面模板,用于实现管理界面的页签功能。Ace是一个功能丰富的代码编辑器,而Bootstrap则是一个流行的前端开发框架,提供了响应式布局和一系列预先设计的组件。...

    ACE库入门(中文)

    ACE库,全称为Adaptive Communication Environment,是一款强大的跨平台网络编程框架,由Dr. Douglas C. Schmidt领导的团队在1995年开发。这个库主要用于构建高度可靠、可伸缩和可移植的分布式系统。ACE库的核心理念...

    ACE Admin官方文档

    ACE Admin 是一个强大的后台管理模板,它基于 Bootstrap 框架构建,提供了丰富的组件和功能,使得开发者可以快速地构建高效、美观的Web管理界面。官方文档是学习和使用 ACE Admin 的重要参考资料,包含了所有组件的...

    ACE资料系列5 - ACE程序员指南 ACE程序员指南:网络与系统编程的实用设计模式

    《ACE程序员指南:网络与系统编程的实用设计模式》是ACE资料系列的第五部分,对于深入理解和应用ACE框架至关重要。这本书是ACE学习者的必备读物,尤其适合那些希望提升网络和系统编程技能的开发者。 ACE(Adaptive ...

    ACE js插件与例子

    ACE JavaScript 插件是一款强大的代码编辑器,常用于在线编程环境、代码片段分享网站和开发者工具。它以其高效的性能、丰富的语言支持以及高度可定制性而受到开发者的喜爱。本篇将详细介绍ACE插件的核心特性、如何...

    Ace Admin Tab页实现

    Ace Admin是一款基于Ace框架的后台管理系统模板,它提供了丰富的UI组件和优雅的界面设计,适合开发Web应用的管理后台。在“Ace Admin Tab页实现”这个主题中,我们将深入探讨如何利用Ace框架来构建和管理Tab页功能。...

    ACE_ADMIN 框架学习手册

    - `ace-elements.js`、`ace-extra.js`:可能是ACE_ADMIN框架中定制的JavaScript插件或者功能模块。 - `ace.js`:ACE_ADMIN框架的主要JavaScript文件,它可能包含了框架的核心功能和API。 5. 在HTML结构中,可以...

    1上篇:ACE技术论文集

    ### ACE自适配通信环境关键技术知识点 #### 一、ACE简介 ACE(Adaptive Communication Environment,自适配通信环境)是一种面向对象(Object-Oriented, OO)的工具包,旨在帮助开发者简化通信软件的开发过程。ACE...

    ace+Admin前端框架

    Ace+Admin前端框架是一款广泛应用在企业级Web应用中的开源UI框架,它结合了Ace和AdminLTE两个优秀的前端组件库,提供了丰富的界面元素、布局选项和交互设计,旨在为开发者提供一个高效、美观且易于定制的开发环境。...

    ACE.rar_ACE_ACE网络库_ACE网络编程_ace 网络库_网络 免费

    ACE(Adaptive Communication Environment)是一个跨平台的网络编程框架,由Dale Schurmann和Douglas C. Schmidt等人开发,广泛应用于分布式系统和实时网络应用。这个“ACE.rar”压缩包包含了ACE网络库的相关资源,...

    aceEditor代码编辑器api

    AceEditor是一款广受欢迎的前端代码编辑器,以其高性能和丰富的API功能著称。这款编辑器支持多种编程语言的代码高亮显示,适用于构建在线代码编辑器、开发者工具或任何需要文本编辑功能的Web应用。在官方文档无法...

    Ace Editor 源码含Demo

    Ace Editor 是一个强大的开源代码编辑器,常用于Web应用程序中,提供丰富的文本编辑功能。它由Ajax.org B.V.开发,最初是Cloud9 IDE的一部分,现在已成为独立的项目,广泛应用于各种在线编程环境和代码编辑工具。这...

    ACE技术内幕:深入解析ACE架构设计与实现原理

    《ace技术内幕:深入解析ace架构设计与实现原理》从构架模式、编程示例和源代码3个维度系统地对经典网络框架ace(adaptivemunicationenvironment)的架构设计和实现原理进行了深入分析,它能解决4个方面的问题:,...

    非常好用的一个ace前端框架

    Ace 前端框架是一款专为后台开发人员设计的强大工具,它填补了开发者在前端技能上的空白,使得那些专注于后端技术的工程师也能轻松应对前端开发任务。Ace 框架以其高效、易用和丰富的功能特性,成为了许多开发团队的...

    ace各个版本下载地址

    根据提供的文件信息,“ace各个版本下载地址”,我们可以深入探讨ACE软件的不同版本以及如何获取它们。 ### ACE软件简介 ACE(Adaptive Communication Environment)是一个开放源代码的中间件框架,主要用于高性能...

    Ace Admin中英文双语版

    Ace Admin是一款广受欢迎的开源后台模板,专为Web应用程序设计,尤其适合开发人员构建管理界面。这个资源包含Ace的中英文双语版本,确保了在不同语言环境下的使用灵活性。Ace框架基于Bootstrap 3,一个强大的前端...

Global site tag (gtag.js) - Google Analytics